20
Misconceptions of `this`
Hello friends,
let's start with what is not
this
... this
isn't bound to :1- the object
this
appears within.2- the function
this
appears within.3- a new instance of the function
this
appears within.The keyword
this
itself doesn't have a value. JS interpreter binds the value of this
when its parent function gets invoked. but would you always trust the JS interpreter to bind the value of this
to the right object
automatically? ... I wouldn't.In other words, when someone shows you a code and asks you:
what is the value of this
here ?
the right answer would be:
show me where the parent function is invoked.
I'll try to sum it up in 5 scenarios:
If the function is called with no context:
function displayName() {
console.log(this);
}
displayName(); // {}
In the code above, the value of
this
inside displayName()
is either the global object
or, if in strict mode, it's undefined
.If the function is a method of an object:
const player = {
name: "Mohamed",
displayName: function () {
console.log(this.name);
},
};
player.displayName(); // "Mohamed"
In the code above, the value of
this
inside displayName()
will refer to player
which actually makes sense because you called the method displayName()
on the object player
. that invocation bound the object player
to this
inside of the method. good job JS interpreter. function Square(color) {
this.color = color;
}
const redSquare = new Square("red");
let's see what the keyword
new
does behind the scenes.without using the keywords
new
and this
, you will have to create and return the object manuallyfunction Square(color){
let obj = {}
obj.color = color
return obj
}
const redSquare = Suare("red");
the keyword
new
actually creates the object for you and binds that object to this
... then return itfunction Square(color){
̶l̶e̶t̶ ̶t̶h̶i̶s̶ ̶=̶ ̶O̶b̶j̶e̶c̶t̶.̶c̶r̶e̶a̶t̶e̶(̶S̶q̶u̶a̶r̶e̶.̶p̶r̶o̶t̶o̶t̶y̶p̶e̶)̶; //{}
this.color = color;
̶r̶e̶t̶u̶r̶n̶ ̶t̶h̶i̶s̶;
}
const redSquare =new Square("red");
In the code above, the value of
this
inside the function is a newly created empty object. So far we have been saying that JS interpreter does all the work automatically for us... do we have control over the value of this ?
Actually, YES we do
we have two 3 methods to change the value of
Actually, YES we do
we have two 3 methods to change the value of
this
const player = {
name: "Mohamed",
displayName: function () {
console.log(this.name);
},
};
const anotherPlayer = { name: "ahmed" };
player.displayName.call(anotherPlayer); // "ahmed"
same as
player.displayName.apply(anotherPlayer)
In the code above, the value of
this
inside displayName()
will refer to anotherPlayer
since the first parameter of call()
or "apply() is to explicitly set what this
refers to.bind()
method is a little bit different because it returns the same function after it sets the value of this
to whatever you wantconst player = {
name: "Mohamed",
displayName: function () {
console.log(this.name);
},
};
const anotherPlayer = { name: "ahmed" };
const displayName = player.displayName.bind(anotherPlayer);
displayName(); // "ahmed"
In the code above,
bind()
set the value of this
inside player.display
to anotherPlayer
and returned a whole new function..... wait what ... why would I use
bind()
...I'll stick to call()
and apply()
.let's say you have this code, a simple function that takes a callback and call it twice.
const player = {
name: "Mohamed",
displayName: function () {
console.log(this.name);
},
};
function callTwice(cb) {
cb();
cb();
}
callTwice(player.displayName);
what do you expect ?? you passed the right function... but look where it's invoked !
the output would be according to rule number # 1
the output would be according to rule number # 1
undefined
undefined
In the code above, the value of
this
will be the global object because that's how its parent function got invoked. Don't worry...
bind()
to the rescueconst callback = player.displayName.bind(player);
callTwice(callback); // "Mohamed"
// "Mohamed"
With regular functions, the value of
this
is set based on how the function is called. With arrow functions, the value of this
is based on the function's surrounding context. In other words, the value of this
inside an arrow function is the same as the value of this
outside the function then apply the rules we mentioned earlier.1- Apply MDN
2- Call MDN
3- Bind MDN
20