Domine o `this` em JavaScript: Guia Completo com Exemplos!

Qual o significado da palavra-chave this em JavaScript? E como você pode empregá-la de maneira prática em seus projetos? Estas são indagações frequentes entre os que estão começando e até mesmo entre desenvolvedores JavaScript mais experientes quando se deparam com essa palavra-chave.

Se você se identifica com esses desenvolvedores que buscam compreender a fundo o this, este artigo foi elaborado pensando em você. Exploraremos a que o this se refere em diferentes cenários e apresentaremos dicas valiosas para evitar confusões e, claro, bugs em seu código.

“this” no Escopo Global

No âmbito global, this apontará para o objeto window, desde que esteja fora de qualquer função. Por escopo global, entendemos aquele em que o this não está inserido dentro de uma função.

 if(true) {
console.log(this)
}

let i = 2
while(i < 10) {
console.log(this)
i++
}

Se você executar o código acima, o resultado será o objeto window.

“this” em Funções (Métodos)

Quando usado dentro de funções, this faz referência ao objeto ao qual a função está atrelada. A exceção ocorre quando this é usado em uma função independente, caso em que retornará o objeto window. Vamos examinar alguns exemplos.

No exemplo a seguir, a função sayName está contida dentro do objeto me (ou seja, é um método). Nesses casos, this se refere ao objeto que hospeda a função.

 
function sayName() {
return `Meu nome é ${this.name}`
}

const me = {
name: "Kingsley",
sayName: sayName
}

console.log(me.sayName())

Nesse caso, this é o objeto me, portanto, usar this.name dentro do método sayName é equivalente a utilizar me.name.

Outra forma de visualizar é que tudo o que estiver à esquerda da função no momento da invocação se tornará o this. Isso significa que você pode reutilizar a função sayName em diferentes objetos e o this se referirá a contextos distintos em cada chamada.

Como mencionado anteriormente, this retorna o objeto window quando usado dentro de uma função independente. Isso acontece porque uma função independente é vinculada ao objeto window por padrão:

 function talk() {
return this
}

talk()

Chamar talk() é o mesmo que chamar window.talk(), e qualquer coisa que esteja à esquerda da função automaticamente se torna o this.

Por outro lado, a palavra-chave this em uma função se comporta de maneira diferente no modo estrito do JavaScript (retorna undefined). Este é um detalhe importante a se considerar ao trabalhar com bibliotecas de UI que usam o modo estrito (por exemplo, React).

Utilizando “this” com Function.bind()

Pode haver situações em que não seja possível simplesmente adicionar uma função a um objeto como um método (como no exemplo anterior).

Talvez o objeto não seja de sua autoria e você o esteja utilizando de uma biblioteca. O objeto é imutável, impedindo que você o altere. Nesses casos, é possível executar a função separadamente do objeto, usando o método Function.bind().

No exemplo a seguir, a função sayName não é um método do objeto me, mas você ainda pode vinculá-la usando bind():

 function sayName() {
return `Meu nome é ${this.name}`
}

const me = {
name: "Kingsley"
}

const meTalk = sayName.bind(me)

meTalk()

Qualquer objeto que você passar para bind() será usado como o valor de this naquela invocação da função.

Em resumo, você pode empregar bind() em qualquer função e inserir um novo contexto (um objeto). Esse objeto substituirá o significado de this dentro da função.

Utilizando “this” com Function.call()

E se você não quiser retornar uma nova função, mas apenas executar a função após vinculá-la ao seu contexto? A solução para isso é o método call():

 function sayName() {
return `Meu nome é ${this.name}`
}

const me = {
name: "Kingsley"
}

sayName.call(me)

O método call() executa a função imediatamente, em vez de retornar outra função.

Caso a função precise de um parâmetro, você pode passá-lo através do método call(). No exemplo a seguir, a língua é passada para a função sayName(), o que permite retornar diferentes mensagens de forma condicional:

 function sayName(lang) {
if (lang === "en") {
return `Meu nome é ${this.name}`
} else if (lang === "it") {
return `Io sono ${this.name}`
}
}

const me = {
name: "Kingsley"
}

sayName.call(me, 'en')
sayName.call(me, 'it')

Como você pode observar, é possível passar qualquer parâmetro desejado para a função como o segundo argumento do método call(). Você também pode incluir quantos parâmetros desejar.

O método apply() é bastante semelhante a call() e bind(). A única distinção é que você passa múltiplos argumentos separados por vírgula com call(), enquanto com apply() você passa vários argumentos dentro de um array.

Resumindo, bind(), call() e apply() permitem que você invoque funções com um objeto completamente diferente, mesmo sem haver qualquer relação entre eles (isto é, a função não precisa ser um método do objeto).

“this” dentro de Funções Construtoras

Se você invocar uma função com a palavra-chave new, ela criará um objeto this e o retornará:

 function person(name){
this.name = name
}

const me = new person("Kingsley")
const her = new person("Sarah")
const him = new person("Jake")

me.name
her.name
him.name

No código acima, foram criados três objetos distintos a partir da mesma função. A palavra-chave new estabelece automaticamente uma ligação entre o objeto que está sendo criado e a palavra-chave this dentro da função.

“this” em Funções de Callback

As funções de callback são diferentes das funções comuns. São funções que você passa para outra função como um argumento, de modo que possam ser executadas após a conclusão da função principal.

A palavra-chave this refere-se a um contexto totalmente diferente quando empregada dentro de funções de callback:

 function person(name){
this.name = name
setTimeout(function() {
console.log(this)
}, 1000)
}

const me = new person("Kingsley")

Após um segundo, ao chamar a função construtora person e criar um novo objeto me, ele registrará o objeto window como o valor de this. Portanto, ao usar em uma função de callback, this faz referência ao objeto window e não ao objeto “construído”.

Existem duas formas de solucionar esse problema. O primeiro método é usar bind() para vincular a função person ao objeto recém-criado:

 function person(name){
this.name = name
setTimeout(function() {
console.log(this)
}.bind(this), 1000)
}

const me = new person("Kingsley")

Com a alteração acima, o this no callback apontará para o mesmo this da função construtora (o objeto me).

A segunda forma de resolver o problema em funções de callback é usando funções de seta.

“this” dentro de Funções de Seta

As funções de seta se distinguem das funções regulares. Você pode transformar sua função de callback em uma função de seta. Com funções de seta, não há mais necessidade de bind(), pois ele se vincula automaticamente ao objeto recém-criado:

 function person(name){
this.name = name
setTimeout(() => {
console.log(this)
}, 1000)
}

const me = new person("Kingsley")

Aprenda mais sobre JavaScript

Você acabou de explorar a fundo a palavra-chave “this” e seus significados em diversos contextos do JavaScript. Se você está começando agora no JavaScript, dominar esses fundamentos e entender como a linguagem opera será de grande valia.