👆
The "this" Keyword
intermediateThe `this` keyword refers to the object that is executing the current function. Its value is determined by HOW a function is called, not where it's defined. There are 4 main rules that determine what `this` refers to.
🎮Interactive Visualization
CodeImplicit Binding
1const person = {2 name: "Alice",3 greet() {4 console.log(this.name);5 }6};78person.greet(); // "Alice"
Execution Context
this =
person
Rule: Object before dot = this
Step 1/2person.greet() is called - look at what's LEFT of the dot
Binding Priority: new → explicit (call/apply/bind) → implicit (dot) → default (global). Arrow functions inherit this lexically from enclosing scope.
Key Points
- this is determined at call time, not definition time
- Rule 1: new binding - this = new instance
- Rule 2: Explicit binding (call/apply/bind) - this = specified object
- Rule 3: Implicit binding (obj.method()) - this = object left of dot
- Rule 4: Default binding - this = window (or undefined in strict mode)
- Arrow functions inherit this from enclosing scope
💻Code Examples
Object Method
const person = {
name: "Alice",
greet() {
console.log("Hi, I'm " + this.name);
}
};
person.greet();
// "Hi, I'm Alice"
// this = object left of the dotImplicit binding: object left of dot
Standalone Function
function showThis() {
console.log(this);
}
showThis();
// In browser: Window object
// In strict mode: undefined
// No object = default bindingDefault binding: no object = global
call() / apply()
function greet(greeting) {
console.log(greeting + ", " + this.name);
}
const bob = { name: "Bob" };
const sue = { name: "Sue" };
greet.call(bob, "Hello");
// "Hello, Bob"
greet.apply(sue, ["Hi"]);
// "Hi, Sue"
// First argument becomes 'this'Explicit binding: first arg = this
bind()
const person = {
name: "Alice",
greet() {
console.log("Hi, " + this.name);
}
};
const greet = person.greet;
greet(); // undefined (lost binding!)
const boundGreet = person.greet.bind(person);
boundGreet(); // "Hi, Alice"
// bind() permanently sets 'this'Hard binding: permanently set this
Arrow Functions
const person = {
name: "Alice",
regularFunc() {
console.log(this.name); // "Alice"
const arrow = () => {
console.log(this.name); // "Alice"
};
arrow();
}
};
// Arrow functions inherit 'this'
// from their enclosing scopeLexical this: inherits from enclosing scope
new Keyword
function Person(name) {
this.name = name;
this.greet = function() {
console.log("Hi, " + this.name);
};
}
const alice = new Person("Alice");
alice.greet(); // "Hi, Alice"
// 'new' creates fresh object
// and binds it to 'this'Constructor binding: this = new instance
Lost Binding
const person = {
name: "Alice",
greet() {
console.log("Hi, " + this.name);
}
};
// BUG: 'this' is lost in callback
setTimeout(person.greet, 100);
// "Hi, undefined"
// The method is passed as plain
// function, losing its contextCommon bug: callback loses context
Fixed with Arrow
const person = {
name: "Alice",
greet() {
console.log("Hi, " + this.name);
}
};
// FIX 1: Arrow function wrapper
setTimeout(() => person.greet(), 100);
// "Hi, Alice"
// FIX 2: Use bind
setTimeout(person.greet.bind(person), 100);
// "Hi, Alice"Arrow function preserves this
Common Mistakes
- Losing this when passing methods as callbacks
- Using arrow functions as object methods
- Forgetting that this in nested functions is different
Interview Tips
- Know all 4 binding rules in order of precedence
- Explain why arrow functions are useful in callbacks
- Be able to fix "this" issues with bind or arrow functions