In JavaScript, the this
keyword is very flexible and confusing, evaluated at runtime, can have different values depending in which context it appears, including but not limited to: function, class, global, and strict mode.
A common mistake for new JavaScript developers is to extract a method from an object, then later call that function and expect it to use the original object as its this
, like using the method in callback-based code.
Here are common contexts in which this
behaves differently:
this
follows the rule of “global object in non-strict, undefined in strict”.function foo() {
console.log(this);
}
foo(); // "window" in browsers, "global" in Node.js
In “strict mode”, the value of this
is always undefined
.
'use strict';
function foo() {
console.log(this);
}
foo(); // undefined
this
refers to the object before dot, the one used to call the method.const person = {
name: 'John',
greet() {
console.log(`Hello, my name is ${this.name}`);
}
};
person.greet(); // Output: Hello, my name is John
this
refers to the HTML element that the event occurred on.const button = document.querySelector('button');
button.addEventListener('click', function() {
console.log(this === button); // Output: true
});
this
refers to the newly created object.function Person(name) {
this.name = name;
}
const john = new Person('John');
console.log(john.name); // Output: John
bind()
: This method creates a new function that, when called, has its this
keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.const person = {
name: 'John',
greet() {
console.log(`Hello, my name is ${this.name}`);
}
};
const greet = person.greet.bind({ name: 'Jane' });
greet(); // Output: Hello, my name is Jane
call()
: This method calls the function with a given this
value and arguments provided individually.const person = {
name: 'John',
greet() {
console.log(`Hello, my name is ${this.name}`);
}
};
person.greet.call({ name: 'Jane' }); // Output: Hello, my name is Jane
apply()
: This method calls the specified function with a given this
value, and arguments provided as an array or an array-like object.const person = {
name: 'John',
greet(city) {
console.log(`Hello, my name is ${this.name} and I live in ${city}`);
}
};
person.greet.apply({ name: 'Jane' }, ['New York']); // Output: Hello, my name is Jane and I live in New York
this
value, but inherit it from the enclosing lexical context.const person = {
name: 'John',
greet: () => {
console.log(`Hello, my name is ${this.name}`);
}
};
person.greet(); // Output: Hello, my name is undefined