Foreword
There is quite a lot of information on the Internet about how this works, but all the time I didnโt have enough literally a little bit to fully figure it out.
Recently I nevertheless, as it seems to me, did this and would like to share with you.
Without many words
We will cover both simple and complex examples - so everyone will be interested.
There are two main points that we will look at:
(1) For functions declared via function () {}, this is calculated at the time of the call.
(2) For arrow functions, this is defined when the function is created.
Let's start with some simple examples.
function globalFunc() {
console.log(this);
}
const globalArrowFunc = () => {
// , this - window/undefined
// , use strict this === undefined
console.log(this);
}
globalFunc(); // undefined
globalArrowFunc(); // undefined
What if we add these functions to the object:
const cat = {
name: 'Pirate',
globalFunc,
globalArrowFunc
};
cat.globalFunc(); // { name: 'Pirate', ... }
cat.globalArrowFunc(); // undefined
Let's figure it out.
Calling cat.globalFunc () returned us a cat object. For ease of understanding, you can think of it like this "this, when calling functions declared via function () {}, will be equal to the object before point".
Then why did cat.globalArrowFunc () return undefined for us? The fact is that the this value for an arrow function is determined at the time of its creation, and when we created it, the this value was undefined.
Now let's create an object with a couple of methods:
const dog = {
name: 'Viking',
//
//
localFunc: function() {
console.log(this);
},
localArrowFunc: () => {
console.log(this);
}
};
dog.localFunc(); // { name: 'Viking', ... }
dog.localArrowFunc(); // undefind
Why is that?
dog.localFunc () - because the object before point dog.
dog.localArrowFunc () - because inside the object this is also a global object, which means we get undefined.
Let's complicate our example a little.
const dog = {
name: 'Viking',
localFunc: function() {
const arrowFuncInLocalFunc = () => {
console.log(this);
};
function funcInLocalFunc() {
console.log(this);
};
arrowFuncInLocalFunc(); // 1
funcInLocalFunc(); // 2
},
localArrowFunc: () => {
const arrowFuncInLocalArrowFunc = () => {
console.log(this);
};
function funcInLocalArrowFunc() {
console.log(this);
};
arrowFuncInLocalArrowFunc(); // 3
funcInLocalArrowFunc(); // 4
}
};
dog.localFunc();
// 1 - { name: 'Viking', ... }
// 2 - undefind
dog.localArrowFunc();
// 3 - undefind
// 4 - undefind
Let's figure it out!
(1) arrowFuncInLocalFunc () // {name: 'Viking',โฆ}
Why is this happening?
Because when we created the object, we wrote it the localFunc function. And, as we remember from the previous examples, for her this is the object before point, that is, {name: 'Viking', ...}. Now let's talk about the arrowFuncInLocalFunc function itself - it is created immediately when localFunc is called and remembers the this value that was at the place of its creation. So we get that arrowFuncInLocalFunc returns us {name: 'Viking',โฆ}.
(2) funcInLocalFunc () // undefind
Why is this happening?
As we said earlier, for functions declared via function () {} the this value is determined at the time of the call and is equal to the object before point. In this case, we do not have an object in front of point, which means this is a global object, or, in our case, undefined.
(3) arrowFuncInLocalArrowFunc () // undefined
Why is this happening?
This example is very similar to (1), only our arrowFuncInLocalArrowFunc function is created inside the same arrow function. We also remember that arrow functions at the time of their declaration write to this value from their environment. However, our function was created inside localArrowFunc, for which this is undefined. This means that for arrowFuncInLocalArrowFunc this will be undefined.
(4) funcInLocalArrowFunc () // undefined
Why is this happening?
Exactly the same reason as in (2) for funcInLocalFunc
Let's look at another example:
const cat = {
name: 'Tom',
getFuncWithTomName: function() {
return () => {
console.log(this.name);
}
}
};
const mouse = {
name: 'Jerry',
logName: cat.getFuncWithTomName()
};
mouse.logName(); // Tom o_O !?
This is because getFuncWithTomName creates and returns an arrow function, and when the arrow function is created, this is the same as that of getFuncWithTomName. And for getFuncWithTomName, this is the object before dot (cat).
Total
The context for arrow functions is determined when they are created.
The context for function () {} is defined when they are called and is equal to the object before point.