A forma como o this é tratado em JavaScript pode gerar confusão, especialmente para iniciantes. Uma afirmação comum em alguns materiais didáticos, como "this é o escopo em que a função está sendo executada", é imprecisa e pode levar a interpretações errôneas. É crucial distinguir entre o escopo de definição de uma função e o escopo em que ela é invocada.
Considere o seguinte cenário:
function outerFunction() {
// ...
}
function middleFunction() {
/// ...
return function innerFunction() {
// ...
};
}
var immediateCall = middleFunction();
outerFunction();
immediateCall();
Neste exemplo, outerFunction, middleFunction e immediateCall (que é innerFunction) são invocadas no escopo global. Portanto, outerFunction e middleFunction executam em um contexto global. Contudo, immediateCall é executada dentro do escopo de middleFunction, não no escopo global. Se innerFunction fizesse referência a this, e considerando a afirmação original, isso implicaria que innerFunction estaria rodando no escopo global, o que contradiz o fato de ela ter sido definida dentro de middleFunction.
Um exemplo mais expplícito demonstra essa distinção:
var globalMessage = 'Olá, escopo global!';
function displayMessage() {
console.log(globalMessage);
console.log(this.globalMessage);
}
var person = {
globalMessage:'Olá, de Pessoas!'
};
person.display = displayMessage;
person.display();
Neste caso, this dentro de displayMessage aponta para person. Se a afirmação de que this representa o escopo de execução fosse verdadeira, então displayMessage estaria sendo executada no contexto de person. Isso significaria que a resolução do nome globalMessage dentro da função começaria por person, resultando em ambas as saídas sendo "Olá, de Pessoas!". Como isso não ocorre na prática, a premissa original é invalidada.
Para evitar confusão, a compreensão do this em JavaScript deve focar nos seguintes pontos:
- Quando uma função é chamada como um método de um objeto,
this(dentro da função, excluindo funções aninhadas) refere-se a esse objeto. - Ao invocar uma função construtora com o operador
new, um novo objeto é criado e a função construtora é executada nesse objeto. Nesse cenário,thisdentro do construtor aponta para esse novo objeto. - Uma chamada de função direta é tratada como uma invocação de método do objeto global.
- Como JavaScript não possui escopo de classe no sentido tradicional, o acesso a propriedades do objeto que invocou um método é feito através de
this.propertyName.
Adicionalmente, a resolução de nomes em JavaScript é importante. Nomes referenciados diretamente são resolvidos na cadeia de escopos da função. Em contrapartida, nomes acessados via objeto.propriedade são resolvidos na cadeia de protótipos do objeto (primeiro no próprio objeto e depois em seus protótipos).