This
If a function has a this
reference inside it, that this
reference usually points to an object. But which object it points to depends on how the function was called.
Here are some examples:
- In a method: When a function is called as a method of an object,
this
refers to the object.
let car = {
make: 'Toyota',
model: 'Camry',
displayCar: function() {
return this.make + ' ' + this.model;
}
};
console.log(car.displayCar()); // Outputs: Toyota Camry
In the displayCar
method, this
refers to the car
object.
- In a regular function (non-method):
this
refers to the global object (in browsers, this is thewindow
).
function myFunction() {
return this;
}
console.log(myFunction() === window); // Outputs: true
- In an event:
this
refers to the element that received the event.
button.addEventListener('click', function() {
this.style.display = 'none'; // 'this' refers to the button
});
- In a constructor function: When a function is used as a constructor (with the
new
keyword),this
refers to the newly created instance.
function Car(make, model) {
this.make = make;
this.model = model;
}
let myCar = new Car('Toyota', 'Camry');
console.log(myCar.make); // Outputs: Toyota
The value of this in JavaScript depends on how a function is invoked (runtime binding), not how it is defined. When a regular function is invoked as a method of an object (obj.method()), this points to that object. When invoked as a standalone function (not attached to an object: func()), this typically refers to the global object (in non-strict mode) or undefined (in strict mode). The Function.prototype.bind() method can create a function whose this binding doesn't change, and methods apply() and call() can also set the this value for a particular call.
const human = {
age: 10,
grow: function () {
return this.age && this.age++;
},
getage: function () {
return this.age;
},
};
const grow = human.grow;
console.log(grow()); //undefined: calling in global context
console.log(human.getage()); // 10: call on human object.
Here's the corrected explanation:
- The
human
object has an age
property initialized with the value 10
. - The
grow
method increments the age
property (if it exists) and returns the current value. - We assign the reference of
human.grow
to the variable grow
. - When we call
grow()
, it behaves differently from invoking it directly on the human
object:- The
this
context inside grow
is determined by how it's called. - Since we call it without any specific context (i.e., not on any object),
this
inside grow
refers to the global object (which is window
in browsers or global
in Node.js). - The expression
this.age && this.age++
evaluates to undefined
(the initial value of age
), and the age
property is not incremented.
- When we call
human.getage()
, it correctly returns the value of the age
property, which is 10
.
Arrow functions
Arrow functions differ in their handling of this: they inherit this from the parent scope at the time they are defined. This behavior makes arrow functions particularly useful for callbacks and preserving context. However, arrow functions do not have their own this binding. Therefore, their this value cannot be set by bind(), apply() or call() methods, nor does it point to the current object in object methods. In other words, when evaluating an arrow function's body, the language does not create a new this binding.
const globalObject = this;
const foo = () => this;
console.log(foo() === globalObject); // true
Arrow functions create a closure over the this value of its surrounding scope, which means arrow functions behave as if they are "auto-bound" — no matter how it's invoked, this is bound to what it was when the function was created (in the example above, the global object). The same applies to arrow functions created inside other functions: their this remains that of the enclosing lexical context.
Constructors
When a function is used as a constructor (with the new keyword), its this
is bound to the new object being constructed, no matter which object the constructor function is accessed on. The value of this
becomes the value of the new
expression unless the constructor returns another non–primitive value.
function C() {
this.a = 37;
}
let o = new C();
console.log(o.a); // 37
function C2() {
this.a = 37;
return { a: 38 };
}
o = new C2();
console.log(o.a); // 38
Super
When a function is invoked in the super.method() form, the this inside the method function is the same value as the this value around the super.method() call, and is generally not equal to the object that super refers to. This is because super.method is not an object member access like the ones above — it's a special syntax with different binding rules.