I am currently learning JavaScript and find the this
keyword really confusing. After struggling with this concept, I've developed a simple framework that helps determine what this
refers to in any situation.
The Two Categories of Functions
JavaScript functions fall into two main categories:
-
Regular functions
- Function declarations:
function name() {}
- Function expressions:
const func = function() {}
- Methods:
object.method()
- Function declarations:
-
Arrow functions
- Arrow functions:
() => {}
- Arrow functions:
Each category handles this
differently, which is the key to understanding its behavior.
Regular Functions: Dynamic this
Binding
For regular functions, this
is determined by how the function is called. There are four binding rules in order of precedence:
Rule 1. Explicit Binding (call
, apply
, bind
): this
is the specified object
function showName() {
console.log(this.name);
}
const person = { name: "Alice" };
showName.call(person); // "this" refers to "person"
Rule 2. Constructor Call (new
): this
is the newly created instance
function Car(name, model) {
this.name = name;
this.model = model;
}
const myCar = new Car("Toyota", "Corolla"); // "this" refers to the new instance "myCar"
Rule 3. Method Call: this
is the object before the dot
const user = {
name: "Charlie",
greet() {
console.log(`Hi, I'm ${this.name}`);
}
};
user.greet(); // "this" refers to "user"
Rule 4. Regular Function Call: this
is the global object or undefined
in strict mode
function standalone() {
console.log(this);
}
standalone(); // "this" refers to the global object or undefined
Arrow Functions: Lexical this
Binding
Arrow functions don't have their own this
. Instead, they inherit this
from the surrounding scope where they were defined.
Rule for arrow functions in a nutshell:
Arrow functions inherit this
from the nearest non-arrow function, i.e., regular function, in their lexical scope. If none exists, this
is the global object or undefined
.
Let's break this down.
Find the nearest non-arrow function in the lexical scope:
1. If found, this
equals that function's this
const obj = {
name: "Example",
outerMethod: function() { // The second nearest regular function
function innerFunction() { // The nearest regular function
const arrowFunc = () => { // This arrow function inherits "this" from innerFunction
console.log(this.name); // "this" is bound to innerFunction's "this" (the global object or undefined)
};
arrowFunc();
}
innerFunction(); // innerFunction's "this" is the global object or undefined (Using "Regular Function Call")
}
};
obj.outerMethod();
2. If not found, this
is the global object or undefined
// Scenario 1: No outer functions
const globalArrow = () => {
console.log(this); // "this" refers to the global object or undefined
};
globalArrow();
// Scenario 2: Outer functions are all arrow functions
const outerArrow = () => {
const innerArrow = () => {
console.log(this); // Still global object or undefined
};
innerArrow();
};
outerArrow();
Decision Framework: Determining this
in Any Situation
To determine what this
refers to, follow this simple flowchart:
1. If it is an arrow function → Find the nearest non-arrow function in the lexical scope:
- If found,
this
equals that function'sthis
- If not found,
this
is the global object orundefined
2. If it is a regular function → Check how it's called (in order of precedence):
- Called with
call/apply/bind
? →this
is the specified object - Called with
new
? →this
is the newly created instance - Called as a method (
obj.method()
)? →this
is the object before the dot - Called as a standalone function? →
this
is the global object orundefined
By categorizing functions as either arrow or regular, and following the binding rules in order of precedence, it is easy to determine what this
refers to in any situation.
Top comments (0)