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.