A palavra-chave this
se refere ao valor do objeto vinculado à
função no momento da chamada. Isso significa que o valor dela é diferente dependendo
de se uma função é chamada como um método, como uma função independente ou como um
construtor.
Quando uma função é chamada, ela cria uma instância da palavra-chave this
em
segundo plano como uma referência ao objeto que contém essa função,
acesso às propriedades e aos métodos definidos ao lado dela no escopo.
O trabalho com this
é semelhante, de certa forma, ao trabalho com uma variável declarada
com const
. Como uma constante, this
não pode ser removido e o valor não pode ser
reatribuído, mas os métodos e as propriedades do objeto que a palavra-chave this
contém podem ser alterados.
Vinculação global
Fora de uma função ou do contexto de um objeto, this
se refere à
propriedade globalThis
, que é uma referência ao objeto global na maioria dos
ambientes JavaScript. No contexto de um script executado em um navegador da Web,
o objeto global é o window
:
this;
> Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, ...}
No Node.js, globalThis
é o objeto global
:
$ node
Welcome to Node.js v20.10.0.
Type ".help" for more information.
> this
<ref *1> Object [global] {
...
}
Fora do modo estrito, this
também se refere ao objeto global dentro de uma função
independente, porque o Window
pai é o objeto que "possui"
essas funções.
function myFunction() {
console.log( this );
}
myFunction();
> Window {...}
(function() {
console.log( this );
}());
> Window {...}
Ao usar o modo restrito, this
tem um valor de undefined
dentro de uma função
independente:
(function() {
"use strict";
console.log( this );
}());
> undefined
Antes da introdução do modo restrito, um valor null
ou undefined
para this
seria substituído por uma referência ao objeto global. Às vezes, a vinculação global é chamada de "vinculação padrão" devido a esse comportamento legado.
Vinculação implícita
Quando uma função é chamada como um método de um objeto, uma instância de this
dentro
desse método se refere ao objeto que contém o método, acesso aos
métodos e propriedades que estão ao lado dele:
let myObject = {
myValue: "This is my string.",
myMethod() {
console.log( this.myValue );
}
};
myObject.myMethod();
> "This is my string."
Pode parecer que o valor de this
depende de como uma função e o
objeto que a contém são definidos. Em vez disso, o contexto do valor de this
é
o contexto de execução atual. Nesse caso, o contexto de execução é que o
objeto myObject
está chamando o método myMethod
. Portanto, myObject
é o valor
para this
. Isso pode parecer uma questão técnica no contexto dos exemplos
anteriores, mas, para usos mais avançados de this
, é uma distinção essencial
a ser considerada.
Em geral, use this
de maneiras que não esperem que o código ao redor tenha
qualquer estrutura específica. A exceção a essa regra são as funções de seta do ES5.
this
em funções de seta
Em funções de seta,
this
é resolvido como uma vinculação em um
ambiente lexicalmente fechado. Isso significa que
this
em uma função de seta se refere ao valor de this
no contexto
mais próximo da função:
let myObject = {
myMethod() { console.log( this ); },
myArrowFunction: () => console.log( this ),
myEnclosingMethod: function () {
this.myArrowFunction = () => { console.log(this) };
}
};
myObject.myMethod();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }
myObject.myArrowFunction();
> Window {...}
No exemplo anterior, myObject.myMethod()
registra myObject
como o objeto
que "possui" esse método, mas myObject.myArrowFunction()
retorna globalThis
(ou undefined
), porque a instância de this
dentro da função de seta
se refere ao escopo mais amplo.
No exemplo abaixo, myEnclosingMethod
cria uma função de seta no
objeto que a contém quando ela é executada. A instância de this
dentro da
função de seta agora se refere ao valor de this
dentro do ambiente
englobante, que é o método que contém essa função de seta. Como o
valor de this
dentro de myEnclosingMethod
se refere a myObject
, depois de
definir a função de seta, this
dentro da função de seta também se refere a
myObject
:
let myObject = {
myMethod() { console.log( this ); },
myEnclosingMethod: function () {
this.myArrowFunction = () => { console.log(this) };
}
};
myObject.myEnclosingMethod();
myObject.myArrowFunction();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }
Vinculação explícita
A vinculação implícita lida com a maioria dos casos de uso para trabalhar com this
. No entanto, às vezes, você
pode precisar que o valor de this
represente um contexto de execução específico, em vez do contexto presumido. Um exemplo ilustrativo, embora um pouco desatualizado,
é trabalhar com this
na função de callback de um setTimeout
,
porque esse callback tem um contexto de execução exclusivo:
var myObject = {
myString: "This is my string.",
myMethod() {
console.log( this.myString );
}
};
myObject.myMethod();
> "This is my string."
setTimeout( myObject.myMethod, 100 );
> undefined
Embora essa limitação específica de setTimeout
tenha sido resolvida por
outros recursos, problemas semelhantes de "perda" de this
foram resolvidos
criando uma referência explícita ao valor de this
no escopo do
contexto pretendido. Às vezes, você pode encontrar instâncias de this
sendo atribuídas
a uma variável usando identificadores como that
, self
ou _this
em bases de código
legado. Estas são convenções de identificador comuns para variáveis que contêm um
valor this
transmitido.
Quando você chama uma função usando os métodos call()
, bind()
ou apply()
,
this
faz referência explícita ao objeto que está sendo chamado:
let myFunction = function() {
console.log( this.myValue );
}
let myObject = {
"myValue" : "This is my string."
};
myFunction.call( myObject );
> "This is my string."
var myObject = {
myString: "This is my string.",
myMethod() {
console.log( this.myString );
}
};
setTimeout( myObject.myMethod.bind( myObject ), 100 );
> "This is my string."
A vinculação explícita substitui o valor this
fornecido pela vinculação implícita.
let myObject = {
"myValue" : "This string sits alongside myMethod.",
myMethod() {
console.log( this.myValue );
}
};
let myOtherObject = {
"myValue" : "This is a string in another object entirely.",
};
myObject.myMethod.call( myOtherObject );
> "This is a string in another object entirely."
Se uma função for chamada de uma maneira que defina o valor de this
como
undefined
ou null
, esse valor será substituído por globalThis
fora do modo
rígido:
let myFunction = function() {
console.log( this );
}
myFunction.call( null );
> Window {...}
Da mesma forma, se uma função for chamada de uma maneira que dê um valor primitivo
a this
, esse valor será substituído pelo
objeto wrapper do valor primitivo
fora do modo estrito:
let myFunction = function() {
console.log( this );
}
let myNumber = 10;
myFunction.call( myNumber );
> Number { 10 }
No modo estrito, um valor this
transmitido não é convertido em um objeto de nenhuma forma,
mesmo que seja um valor primitivo, null
ou undefined
:
"use strict";
let myFunction = function() {
console.log( this );
}
let myNumber = 10;
myFunction.call( myNumber );
> 10
myFunction.call( null );
> null
Vinculação de new
Quando uma classe é usada como um construtor usando a
palavra-chave new
, this
se refere à instância recém-criada:
class MyClass {
myString;
constructor() {
this.myString = "My string.";
}
logThis() {
console.log( this );
}
}
const thisClass = new MyClass();
thisClass.logThis();
> Object { myString: "My string." }
Da mesma forma, o valor de this
dentro de uma função de construtor chamada usando new
se refere ao objeto que está sendo criado:
function MyFunction() {
this.myString = "My string.";
this.logThis = function() {
console.log( this );
}
}
const myObject = new MyFunction();
myObject.logThis();
> Object { myString: "My string.", logThis: logThis() }
Vinculação de manipuladores de eventos
No contexto de manipuladores de eventos, o valor de this
faz referência ao objeto que
o invoca. Dentro da função de callback de um manipulador de eventos, isso significa que this
faz referência ao elemento associado ao gerenciador:
let button = document.querySelector( "button" );
button.addEventListener( "click", function( event ) { console.log( this ); } );
Quando um usuário interage com o button
no snippet anterior, o resultado é
o objeto de elemento que contém o <button>
:
> Button {}
Quando uma função de seta é usada como um callback de listener de eventos, o valor de
this
é fornecido novamente pelo contexto de execução mais próximo. No nível
superior, isso significa que this
dentro de uma função de callback do gerenciador de eventos é
globalThis
:
let button = document.querySelector( "button" );
button.addEventListener( "click", ( event ) => { console.log( this ); } );
> undefined
Como qualquer outro objeto, quando você usa os métodos call()
, bind()
ou apply()
para referenciar a função de callback de um listener de eventos, o this
faz referência ao objeto explicitamente:
let button = document.querySelector( "button" );
let myObject = {
"myValue" : true
};
function handleClick() {
console.log( this );
}
button.addEventListener( "click", handleClick.bind( myObject ) );
> Object { myValue: true }
Teste seu conhecimento
Para um script executado em um navegador da Web, qual é o objeto global
a que this
se refere quando usado fora de uma função ou do
contexto de um objeto?
window
browser
undefined