What is 'this'?
In short, this
in JavaScript references the object that is executing the current function.
How then do we determine the object being referenced?
(#1.) If the function is part of an object (ie. a method), this
references the object.
const bird = {
name: "Tweety",
printThis() {
console.log(this); // `this` references `bird`
}
};
bird.printThis(); // { name: 'Tweety', printThis: ƒ }
(#2.) If the function is a regular function (not part of an object), this
references the global object in the running environment (ie. window in browsers and global in node)
function bird() {
console.log(this);
}
// If called in browser:
bird(); // Window {stop: ƒ, open: ƒ, alert: ƒ, ...}
Note: if a method has a callback function, this
in the callback function references the global object.
const bird = {
birdName: "tweety",
sounds: ["chirp", "quack", "tweet"],
printBirdSounds() {
this.sounds.forEach(function(sound) {
console.log(this.birdName, sound);
});
}
};
bird.printBirdSounds(); // undefined 'chirp'
// undefined 'quack'
// undefined 'tweet'
In the above example, this.sounds
in the printBirdSounds()
method correctly references the bird
object as it follows rule 1 above.
However, as the line logging this.birdName
is inside a regular function, this
now follows rule 2 and references the global object. Since there is no birdName
property on the global object, it prints undefined
.
To fix this, see rule 4 below.
(#3.) If the function is called using the new
keyword in the case of constructor functions, this
references a new empty object.
function Bird() {
console.log(this);
this.name = "tweety";
console.log(this);
}
new Bird();
// {}
// { name: 'tweety' }
(#4.) If this
is used in an arrow function, the value of this is inherited from its enclosing scope (ie. follow lexical scoping rules).
This is because arrow functions do not have their own this
value.
Rewriting the second example in rule 2 using arrow functions,
const bird = {
birdName: "tweety",
sounds: ["chirp", "quack", "tweet"],
printBirdSounds() {
this.sounds.forEach(sound => console.log(this.birdName, sound));
}
};
bird.printBirdSounds(); // tweety 'chirp'
// tweety 'quack'
// tweety 'tweet'
With arrow functions, the line logging this.birdName
now follows rule 1 and references the bird object!
(#5.) If bind
, call
, apply
are used to call a function, this
inside the function is the object that is passed in as the argument.
function bird() {
console.log(this);
}
const tweety = {
sound: "tweet"
};
const bindTweety = bird.bind(tweety);
bindTweety(); // { sound: 'tweet' }
bird.call(tweety); // { sound: 'tweet' }
bird.apply(tweety); // { sound: 'tweet' }
Top comments (2)
Thanks, finally I understand the use of "this" inside the arrow functions!! Good examples!!
This is very well explained. Thanks.