this is not “the object a function belongs to.” In JavaScript, its value is usually determined by how a function is called, not where the function was written.
Method calls
1 | const cat = { |
The receiver before the dot becomes this. But extracting the function removes that receiver:
1 | const speak = cat.speak; |
Explicit binding
call, apply, and bind select the receiver explicitly:
1 | function greet(greeting) { |
bind returns a new function whose this is fixed.
Constructor calls
With new, JavaScript creates an object and binds it as this inside the constructor:
1 | function User(name) { |
Arrow functions
Arrow functions do not create their own this. They capture it lexically from the surrounding scope:
1 | const counter = { |
That makes arrows useful for callbacks inside methods, but usually wrong as object methods when dynamic receiver binding is required.
Global context is environment-dependent
At the top level of a browser classic script, this may be window. In an ES module, top-level this is undefined. In Node.js CommonJS modules, top-level this is not the global object. Therefore “this alone is always global” is not a portable rule.
A practical decision tree
- Called with
new?thisis the new instance. - Called with
call,apply, or a bound function? Use the explicit receiver. - Called as
object.method()?thisisobject. - Arrow function? Inherit
thisfrom the surrounding scope. - Plain function call?
undefinedin strict mode; legacy non-strict behavior may use the global object.
The keyword is not random. It is just context-sensitive enough to punish vague mental models.