A palavra-chave this
refere-se ao valor do objeto que está vinculado à
função no momento da chamada, o que significa que o valor é diferente, dependendo
de uma função ser chamada como método, como uma função autônoma 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, concedendo acesso às propriedades e aos métodos definidos com ela de dentro do escopo.
Trabalhar com this
é semelhante em algumas maneiras a trabalhar com uma variável declarada
com const
. Assim como uma constante, this
não pode ser removido e seu valor não pode ser
reatribuído, mas os métodos e 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
refere-se à propriedade globalThis
, que é uma referência ao objeto global na maioria dos ambientes JavaScript. No contexto de um script em execução em um navegador da Web, o objeto global é o window
:
this;
> Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, ...}
Em 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 estrito, 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 pode ser chamada de "vinculação padrão" devido a esse comportamento legado.
Vinculação implícita
Quando uma função é chamada como método de um objeto, uma instância de this
dentro
desse método se refere ao objeto que contém o método, concedendo acesso aos
métodos e propriedades ao lado:
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 dela estã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
de this
. Isso pode parecer técnico no contexto dos exemplos
anteriores, mas, para usos mais avançados de this
, é uma distinção essencial
a ter em mente.
Em geral, use this
de maneiras que não esperem que o código circundante tenha
uma 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 que abrange lexicamente. Isso significa que this
em uma função de seta se refere ao valor de this
no contexto de inclusão mais próximo dessa 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 de inclusão mais alto.
No exemplo a seguir, myEnclosingMethod
cria uma função de seta no objeto que a contém quando é executado. A instância de this
dentro da função de seta agora se refere ao valor de this
dentro do ambiente delimitado, 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 que você 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 processa a maioria dos casos de uso para trabalhar com this
. No entanto, às vezes você
pode precisar do valor de this
para representar um contexto de execução específico, em vez do contexto presumido. Um exemplo ilustrativo, se ligeiramente desatualizado,
está funcionando 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 deficiência específica de setTimeout
tenha sido resolvida por
outros recursos, problemas semelhantes de "perda" de this
foram resolvidos
anteriormente com a criação de uma referência explícita ao valor de this
no escopo do
contexto pretendido. É possível que você veja instâncias de this
sendo atribuídas
a uma variável usando identificadores como that
, self
ou _this
em bases de código
legadas. 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
estrito:
let myFunction = function() {
console.log( this );
}
myFunction.call( null );
> Window {...}
Da mesma forma, se uma função for chamada de uma maneira que forneça a this
um valor
primário, esse valor será substituído pelo
objeto wrapper do valor primitivo
fora do modo restrito:
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,
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 construtor com 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 do manipulador 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 manipulador:
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 próprio <button>
:
> Button {}
Quando uma arrow function é usada como um callback de listener de eventos, o valor de this
é novamente fornecido pelo contexto de execução delimitado mais próximo. No nível superior, isso significa que o this
dentro de uma função de callback do manipulador de eventos é
globalThis
(ou undefined
, no modo estrito):
let button = document.querySelector( "button" );
button.addEventListener( "click", ( event ) => { console.log( this ); } );
> undefined
Como acontece com 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, this
referencia o 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
No caso de um script em execução 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