By the end of this lesson, you will be able to predict what this refers to in a JavaScript function by looking at how the function is called.
What it is
In JavaScript, this is a special keyword that refers to the current execution context of a function. For ordinary functions, this is not fixed when the function is written; it is decided when the function is called. This is called call-site binding.
Related terms include implicit binding, where a method is called through an object; explicit binding, where call, apply, or bind sets this; new binding, where this refers to the newly created object; and default binding, where a plain function call has no object receiver. Arrow functions are different: they do not have their own this and inherit it from the surrounding lexical scope.
Why it matters
- It explains why the same function can behave differently when called in different ways.
- It helps you debug errors like
Cannot read properties of undefinedinside methods. - It is essential when passing methods as callbacks, event handlers, or timers.
- It clarifies when to use regular functions versus arrow functions.
- It makes object-oriented JavaScript, such as methods and constructors, easier to reason about.
Syntax or steps
The smallest useful pattern is to inspect the call site:
obj.method();
obj.method.call(otherObj);
new Constructor();
plainFunction();
For ordinary functions, use this order:
- If the function is called with
new,thisis the new object. - If the function is called with
call,apply, orbind,thisis the provided object. - If the function is called as a method, such as
obj.method(),thisisobj. - Otherwise, default binding applies: in strict mode,
thisisundefined; in sloppy mode, it is the global object.
Example
"use strict";
const user = {
name: "Ada",
greet() {
return `Hello, ${this.name}`;
}
};
const other = { name: "Grace" };
function whoAmI() {
return this;
}
console.log(user.greet());
console.log(user.greet.call(other));
console.log(whoAmI());
Expected output:
Hello, Ada
Hello, Grace
undefined
Part by part:
user.greet()uses implicit binding. The object before the dot isuser, sothisisuser.user.greet.call(other)uses explicit binding.callforcesthisto beother.whoAmI()uses default binding. Because the code is strict and there is no object receiver,thisisundefined.
Common mistakes
- Assuming
thisis fixed when the function is defined. Fix: look at the call site, not the definition. - Losing the binding when passing a method as a callback. Fix: use an arrow wrapper or
bind. - Using an arrow function for an object method that needs
this. Fix: use a regular function or method shorthand. - Forgetting strict mode changes default binding. Fix: remember that a plain function call in strict mode gives
this === undefined.
When to use it
| Need | Use | Why |
|---|---|---|
| Method that should refer to its object | Regular function or method shorthand | Call-site binding lets obj.method() set this to obj. |
Callback that should keep surrounding this |
Arrow function | Arrow functions inherit this from the enclosing scope. |
| One-time call with a specific receiver | call or apply |
They explicitly set this at call time. |
| Reusable function with a fixed receiver | bind |
It creates a new function with this preset. |
Practice
Guided exercise: predict the output.
"use strict";
const box = {
label: "Books",
show() {
return this.label;
}
};
const fn = box.show;
console.log(box.show());
console.log(fn.call(box));
Expected output:
Books
Books
Challenge: fix this code so it logs Ada instead of throwing.
"use strict";
const user = {
name: "Ada",
greet() {
console.log(this.name);
}
};
setTimeout(user.greet, 100);
Solution hint: wrap the call in an arrow function, or bind the method to user.
Quick check
Question: If a function is called as obj.method(), what is this?
Answer: obj, because the method is called with an implicit binding to the object before the dot.
Summary
JavaScript’s this is usually determined by how a function is called, not where it is defined. Check for new, explicit binding, method calls, and default calls in that order. Arrow functions are the main exception because they inherit this from their surrounding scope.