Prefácio
Há muitas informações na Internet sobre como isso funciona, mas o tempo todo eu não tinha literalmente um pouco o suficiente para entendê-lo completamente.
Recentemente, no entanto, como me parece, fiz isso e gostaria de compartilhar com vocês.
Sem muitas palavras
Cobriremos exemplos simples e complexos - para que todos se interessem.
Há dois pontos principais que examinaremos:
(1) Para funções declaradas por meio de function () {}, isso é calculado no momento da chamada.
(2) Para funções de seta, isso é definido quando a função é criada.
Vamos começar com alguns exemplos simples.
function globalFunc() {
console.log(this);
}
const globalArrowFunc = () => {
// , this - window/undefined
// , use strict this === undefined
console.log(this);
}
globalFunc(); // undefined
globalArrowFunc(); // undefined
E se adicionarmos essas funções ao objeto:
const cat = {
name: 'Pirate',
globalFunc,
globalArrowFunc
};
cat.globalFunc(); // { name: 'Pirate', ... }
cat.globalArrowFunc(); // undefined
Vamos descobrir.
Chamar cat.globalFunc () nos retornou um objeto gato. Para facilitar o entendimento, você pode pensar assim "isso, ao chamar funções declaradas por meio da função () {}, será igual ao objeto antes do ponto".
Então, por que cat.globalArrowFunc () retornou undefined para nós? O fato é que o valor this para uma função seta é determinado no momento de sua criação, e quando a criamos, o valor this era indefinido.
Agora, vamos criar um objeto com alguns métodos:
const dog = {
name: 'Viking',
//
//
localFunc: function() {
console.log(this);
},
localArrowFunc: () => {
console.log(this);
}
};
dog.localFunc(); // { name: 'Viking', ... }
dog.localArrowFunc(); // undefind
Por que é que?
dog.localFunc () - porque o objeto antes do ponto dog.
dog.localArrowFunc () - porque dentro do objeto também é um objeto global, o que significa que ficamos indefinidos.
Vamos complicar um pouco nosso exemplo.
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
Vamos descobrir!
(1) arrowFuncInLocalFunc () // {name: 'Viking',…}
Por que isso está acontecendo?
Porque quando criamos o objeto, escrevemos a função localFunc. E, como lembramos dos exemplos anteriores, para ela este é o objeto antes do ponto, ou seja, {nome: 'Viking', ...}. Agora vamos falar sobre a função arrowFuncInLocalFunc em si - ela é criada imediatamente quando localFunc é chamado e lembra o valor this que estava no local de sua criação. Então, obtemos que arrowFuncInLocalFunc nos retorna {nome: 'Viking',…}.
(2) funcInLocalFunc () // undefind
Por que isso está acontecendo?
Como dissemos anteriormente, para funções declaradas via function () {} esse valor é determinado no momento da chamada e é igual ao objeto antes do ponto. Nesse caso, não temos um objeto na frente do ponto, o que significa que este é um objeto global ou, no nosso caso, indefinido.
(3) arrowFuncInLocalArrowFunc () // undefined
Por que isso está acontecendo?
Este exemplo é muito semelhante a (1), apenas nossa função arrowFuncInLocalArrowFunc é criada dentro da mesma função de seta. Também lembramos que as funções de seta no momento de sua declaração gravam nesse valor a partir de seu ambiente. No entanto, nossa função foi criada dentro de localArrowFunc, para a qual ele é indefinido. Isso significa que para arrowFuncInLocalArrowFunc isso será indefinido.
(4) funcInLocalArrowFunc () // undefined
Por que isso está acontecendo?
Exatamente o mesmo motivo de (2) para funcInLocalFunc.
Vejamos outro exemplo:
const cat = {
name: 'Tom',
getFuncWithTomName: function() {
return () => {
console.log(this.name);
}
}
};
const mouse = {
name: 'Jerry',
logName: cat.getFuncWithTomName()
};
mouse.logName(); // Tom o_O !?
Isso ocorre porque getFuncWithTomName cria e retorna uma função de seta e, quando a função de seta é criada, é igual a getFuncWithTomName. E para getFuncWithTomName, este é o objeto antes do ponto (cat).
Total
O contexto das funções de seta é determinado quando são criadas.
O contexto para function () {} é determinado quando eles são chamados e é igual ao objeto antes do ponto.