The "this" Keyword
Learn how JavaScript decides what "this" refers to based on how a function is called, why arrow functions behave differently, and how to fix a "this" that gets lost in a callback.
Reading Time
18 min
Lesson
Lesson 37 of 48
this Depends on How a Function is Called
The single most important rule about this is that its value is determined by how a function is called, not by where the function is defined. The same function can produce a completely different this depending on whether you call it as a standalone function, as a method on an object, with .call()/.apply(), or with the new keyword. This trips up a lot of developers coming from languages where a method's receiver is fixed at definition time — in JavaScript, this is decided fresh at call time.
this in the Global Context
When this is used outside of any function, it refers to the global object — window in a browser, or global in Node. Inside a regular function called on its own (not as a method), this is undefined in strict mode (which includes the top level of ES modules and class bodies), or falls back to the global object in non-strict, 'sloppy' mode.
this Outside of Any Object
Console Output
Click “Run” to see the console output here.
this Inside an Object Method
When a function is called as a method — that is, accessed off an object right before being invoked, like obj.method() — this inside that function refers to the object it was called on. This is the most common and intuitive use of this: it lets a method read and update the data that belongs to its own object.
this Inside a Method Call
Console Output
Click “Run” to see the console output here.
Regular Functions vs. Arrow Functions
Regular functions get their own this, freshly determined every time they're called. Arrow functions do not have their own this at all — instead, they capture this lexically from the scope in which they were defined, exactly the way closures capture variables. That means an arrow function's this is whatever this was in the surrounding code where the arrow function was written, and it never changes no matter how the arrow function is later called.
Arrow Functions Inherit this Lexically
Console Output
Click “Run” to see the console output here.
Losing this in a Callback
A very common bug happens when a method is passed around as a plain reference — for example, to setTimeout(), an event listener, or as a callback argument. Once a method is detached from the object it was defined on, calling it no longer counts as obj.method(), so this is no longer bound to obj. The function is called on its own, and this reverts to undefined (in strict mode) or the global object.
this Getting Lost
Console Output
Click “Run” to see the console output here.
Fixing it with bind(), call(), and apply()
JavaScript gives you three built-in tools to explicitly control what this refers to. .call(thisArg, ...args) and .apply(thisArg, argsArray) both invoke a function immediately with this set to whatever you pass as the first argument — they differ only in how they accept the remaining arguments. .bind(thisArg) is different: it doesn't call the function, it returns a brand-new function with this permanently locked to thisArg, which is exactly what you want when passing a method somewhere else to be called later.
Fixing a Lost this
Console Output
Click “Run” to see the console output here.
call() vs. apply() vs. bind()
| Method | Invokes Immediately? | How Extra Args Are Passed | Returns |
|---|---|---|---|
| call() | Yes | Listed one by one | The function’s return value |
| apply() | Yes | As a single array | The function’s return value |
| bind() | No | Listed one by one (optional, preset) | A new function with this locked |
this Inside a Class
Inside a class, this behaves like it does in a regular object method: within an instance method, this refers to the specific instance the method was called on. But the same danger applies — if you pass a class method as a callback without binding it, this will be lost. This is why you often see this.method = this.method.bind(this) inside class constructors, or class fields defined as arrow functions, which lexically capture the instance this and never lose it.
this Inside a Class, and How to Protect It
Console Output
Click “Run” to see the console output here.
Quick Rules for Figuring Out this
- Called as obj.method() → this is obj
- Called as a plain function() → this is undefined (strict mode) or the global object
- Called with new Constructor() → this is the newly created instance
- Called with .call()/.apply() → this is whatever you passed in
- Defined as an arrow function → this is inherited from the enclosing scope, always
Watch Out When Passing Methods Around
Any time you extract a method off an object and hand it somewhere else — a callback, an event listener, a setTimeout() — you are at risk of losing this. Always ask: 'is this function still being called as obj.method(), or has it been detached?' If it's detached, either bind it first, wrap it in an arrow function at the call site, or convert it to an arrow function class field.
When in Doubt, console.log(this)
If you're ever unsure what this will be inside a particular function, the fastest way to find out is to log it right there and run the code — this depends entirely on the call site, so reasoning about the source code alone can be misleading, especially with callbacks.