A palavra-chave this em JavaScript confunde desenvolvedores JavaScript novos e experientes. Este artigo pretende elucidar a questão de uma vez, deixando claro como usar this corretamente em todos os cenários, incluindo situações mais peculiares em que normalmente this se revela mais difícil de ser compreendido.

Em JavaScript, usa-se this de forma semelhante ao uso de pronomes em linguagens naturais, como o inglês ou francês. Escreve-se: “João está correndo rápido porque ele está tentando pegar o trem”. Note o uso do pronome “ele”. Poderia se ter escrito: “João está correndo rápido porque João está tentando pegar o trem”. Não se reutiliza “João” dessa maneira, pois se assim fosse, nossa família, amigos e colegas nos abandonariam… De uma maneira graciosamente semelhante, em JavaScript se usa a palavra-chave this como um atalho, um referente; ou seja, o sujeito no contexto ou o sujeito do código em execução.

Exemplo:

Se se usa person.firstName e person.lastName, tal como no último exemplo, o código se torna ambíguo. Considere que poderia haver outra variável global (você estando ciente dela ou não) com o nome “person”. Em seguida, as referências a person.firstName poderiam tentar acessar a propriedade firstName da variável global person e isso poderia levar a erros difíceis de serem depurados. Portanto, usa-se a palavra-chave this não apenas para fins “estéticos” (isto é, como um referente), mas, também, para fins de precisão. Seu uso realmente torna o código mais inequívoco, assim como o pronome “ele” tornou a frase mais clara, informando que se estava referindo ao João específico do início da frase.

Assim como o pronome “ele” é usado para se referir ao antecedente (substantivo a que um pronome se refere), a palavra-chave this é similarmente usada para se referir a um objeto a que a função (onde this é usado) está vinculada. Esta palavra-chave não se refere apenas ao objeto, mas também contém o valor do objeto. Assim como o pronome, isso pode ser pensado como um atalho (ou um substituto razoavelmente não-ambíguo) para se referir ao objeto no contexto (o “objeto antecedente”).

O básico sobre this em JavaScript

Primeiramente, é preciso saber que todas as funções em JavaScript têm propriedades, assim como os objetos têm propriedades. E quando uma função é executada, ela obtém a propriedade this — uma variável com o valor do objeto que invoca a função na qual this é usado.

A referência ao this sempre se refere a (e contém o valor de) um objeto — um objeto singular — e normalmente é usado dentro de uma função ou método, embora possa ser usado fora de uma função no escopo global.

Quando em modo estrito (strict mode), this mantém o valor undefined em funções globais e em funções anônimas que não estão vinculadas a nenhum objeto.

this é usado dentro de uma função (digamos função “A”) e ele contém o valor do objeto que invoca a função A. Isso é preciso para acessar métodos e propriedades do objeto que invoca a função A, especialmente porque nem sempre é possível saber o nome do objeto invocador e, às vezes, não há nenhum nome para usar para se referir ao objeto invocando. Na verdade, this é realmente apenas um atalho-referência ao “objeto antecedente” (ou o objeto invocador).

Reflita sobre este exemplo básico que ilustra o uso de this em Javascript:

E também considere este exemplo em jQuery:

Explicando melhor o exemplo jQuery anterior: o uso de $( this ), que é a sintaxe da jQuery para esta palavra-chave em JavaScript, é usado dentro de uma função anônima, que é executada no “on click” do botão. A razão pela qual $( this ) está vinculado ao objeto de botão é porque a jQuery vincula $( this ) ao objeto que invoca o método de clique. Portanto, $( this ) terá o valor do objeto jQuery ($( 'button' )) mesmo que $( this ) seja definido dentro de uma função anônima que não pode acessar a variável “this” na função externa.

Importante ressaltar que o botão é um elemento DOM na página HTML e também é um objeto; neste caso, é um objeto jQuery porque está envolvido na função jQuery $().

A maior pegadinha com this em JavaScript

Se você entender este princípio de JavaScript, você entenderá a palavra-chave “this”: não é atribuído um valor a this até que um objeto invoque a função na qual this é definido.

Para fins didáticos, considere onde this está definido como “Função this”. Mesmo que pareça que this se refere ao objeto onde ele é definido, isso só acontece quando um objeto chama a “Função this” a que this está atualmente atribuído. E o valor atribuído é baseado exclusivamente no objeto que invoca a “Função this”.

this tem o valor do objeto sendo invocado na maioria das circunstâncias. No entanto, existem alguns cenários nos quais this não tem o valor do objeto sendo invocado. Cenários estes visto mais à frente.

O uso de this em escopo global

No escopo global, quando o código está sendo executado no navegador, todas as variáveis globais e funções são definidas no objeto window. Portanto, quando se usa this em uma função global, ele se refere a (e tem o valor de) o objeto window global — não no strict mode, como observado anteriormente –, que é o contêiner principal de toda a aplicação JavaScript ou página da web.

Deste modo:

Quando this é mal compreendido e se torna complicado

A palavra-chave this é mais mal compreendida em “métodos emprestados”; quando se atribui um método que usa this para uma variável; quando uma função que usa this é passada como uma função de callback e; quando this é usado dentro de uma closure (uma função interna).

Um pouco sobre “contexto” antes de continuar

O contexto em JavaScript é semelhante ao assunto de uma frase na escrita normal. Na frase “João é o vencedor quem devolveu o dinheiro.” o sujeito da sentença é João e é possível afirmar que o contexto da sentença também é João porque o foco da sentença está nele neste momento particular da sentença. Mesmo o pronome “quem” está se referindo a João, o antecedente. E tal como é possível usar um ponto-e-vírgula para mudar o assunto da frase, também é possível ter um objeto que é o contexto atual e mudar o contexto para outro objeto invocando a função com outro objeto.

Similarmente, em código JavaScript:

Ajustando this quando usado em um método callback

As coisas ficam um pouco cabeludas quando passamos um método (que usa this) como um parâmetro para ser usado como uma função de retorno (callback). Por exemplo:

No código acima, uma vez que o botão ($( 'button' )) é um objeto e se está passando o método user.clickHandler() no clique como um callback, sabe-se que this dentro do método user.clickHandler() não mais se refere ao objeto user. this agora se refere ao objeto em que o método user.clickHandler é executado porque este é definido dentro do método user.clickHandler. E o objeto que invoca user.clickHandler é o objeto de botão — user.clickHandler será executado dentro do método de clique do objeto-botão.

Importante observar que, mesmo que se esteja chamando o método clickHandler() através de user.clickHandler (o que é preciso fazer, já que “clickHandler” é um método definido no “user”), o método clickHandler() será executado com o objeto button como contexto para que “this” agora se refere. Então, this agora se refere ao objeto de botão ($( 'button' )).

Neste ponto, deve ser claro quando o contexto muda — quando se executa um método em algum outro objeto do qual o objeto foi originalmente definido, a palavra-chave this já não se refere ao objeto original, no qual this foi originalmente definido, mas se refere ao objeto que invoca o método onde this foi definido.

Solução para corrigir this quando um método é passado como uma função de callback

Como realmente se quer que this.data faça referência à propriedade de dados no objeto “user”, é possível usar os métodos bind(), apply() ou call() para definir especificamente o valor de this.

Ao invés dessa linha:

Deve-se usar bind() para clickHandler, assim:

Ajustando this dentro de um closure

Outro exemplo de quando this é mal compreendido é quando se usa um método interno ou closure. É importante observar que closures não podem acessar a função externa dessa variável usando a palavra-chave this porque essa variável é acessível somente pela própria função e não por funções internas. Por exemplo:

this dentro da função anônima não pode acessar o this da função externa, então ele se refere ao objeto global window (quando o strict mode não está sendo usado).

Solução para manter this dentro de funções anônimas

Para sanar a questão, usa-se uma prática comum em JavaScript: atribuir o valor de this a uma variável antes de entrar no forEach:

É bastante comum na comunidade JavaScript escolher o nome “that” para este tipo de “contorno”, caso em que a atribuição da variável (e posteriores referências) ficariam como:

Ajustando this quando método é atribuído a uma variável

Se se atribui um método que usa this a uma variável, o valor de this quase escapa à imaginação. Como em:

Solução para manter this quando um método é atribuído a uma variável

É possível sanar a questão definindo especificamente o valor de this com o método bind:

Ajustando this em “métodos emprestados”

“Métodos emprestados” é uma prática comum no desenvolvimento em JavaScript. Veja o exame da relevância de this no contexto de métodos emprestados.

this do método avg não se referirá ao objeto gameController; ele se referirá ao objeto appController porque está sendo chamado no appController.

Solução para manter this quando um método é atribuído a uma variável

Para corrigir o problema com a garantia de que o this dentro do método appController.avg() se refere a gameController, usa-se o método apply() assim:

O objeto gameController toma emprestado o método avg() de appController. this dentro do método appController.avg() será definido para o objeto gameController porque se passa o objeto gameController como o primeiro parâmetro de apply() — o primeiro parâmetro no método apply() sempre define o valor de this explicitamente.

Palavras finais sobre o this em JavaScript

Como visto, this fica um pouco problemático em situações onde o contexto original muda, especialmente em funções de callback, quando invocado com um objeto diferente ou em métodos emprestados. Lembre-se: this é atribuído ao valor do objeto que invocou a função. Mas, ao terminar de ler este artigo, certamente você aprender e/ou revisou o suficiente sobre this em JavaScript e agora tem as ferramentas e técnicas necessárias para trabalhar nos cenários mais inóspitos.

Com o advento do ECMAScript 6, alteraram-se algumas das maneiras apresentadas de se trabalhar com o this. Mas não se preocupe, no futuro haverá artigos no desenvolvimento para a web abordando essa atualização.

Até lá, bons códigos e boa sorte!