A palavra-chave "This"

A palavra-chave this refere-se ao valor do objeto vinculado à função no momento de sua chamada, o que significa que seu valor é diferente dependendo se uma função é chamada como método, função autônoma ou construtor.

Quando uma função é chamada, ela cria uma instância da palavra-chave this atrás as cenas como referência ao objeto que contém aquela função, concedendo as propriedades e os métodos definidos junto com ela de dentro do seu escopo. Trabalhar com this é, em alguns aspectos, semelhante a trabalhar com uma variável declarada com const. Como uma constante, this não pode ser removida, e o valor dela não pode ser reatribuído, mas os métodos e propriedades do objeto em 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 ao globalThis, que é uma referência ao objeto global na maioria ambientes JavaScript. No contexto de um script em execução em um navegador da Web, o objeto global é o objeto 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, porque o Window pai é o objeto que efetivamente "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:

(function() {
   
"use strict";
    console
.log( this );
}());
> undefined

Antes da introdução do modo estrito, um valor null ou undefined para this é substituída por uma referência ao objeto global. Às vezes, você pode ver uma vinculação global, conhecida como "vinculação padrão", devido a esse comportamento legado.

Vinculação implícita

Quando uma função é chamada como o método de um objeto, uma instância de this dentro o método se refere ao objeto que contém o método, concedendo acesso ao e as propriedades que acompanham:

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 objeto em anexo estejam 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 O objeto myObject está chamando o método myMethod, então myObject é o valor para this. Isso pode parecer um aspecto técnico no contexto exemplos, mas para usos mais avançados de this, é uma distinção essencial para ter em mente.

Em geral, use this de maneiras que não esperem que o código circundante tenha qualquer estrutura específica. A exceção a essa regra é ES5 Funções de seta.

this nas funções de seta

Em funções de seta, this se refere a uma vinculação em uma ambiente lexicamente incluído. Isso significa que this em uma arrow function refere-se ao valor de this na contexto mais próximo:

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” nesse método, mas myObject.myArrowFunction() retorna globalThis (ou undefined), porque a instância de this dentro da função de seta em vez disso, refere-se ao mais alto escopo.

No exemplo a seguir, myEnclosingMethod cria uma função de seta no que o contém quando executado. A instância de this dentro A arrow function agora se refere ao valor de this ambiente, que é o método que contém essa função de seta. Como o o valor de this em 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 pode precisar do valor de this para representar uma execução específica. contexto, em vez do contexto presumido. Uma descrição ilustrativa, embora um pouco desatualizada, exemplo é trabalhar com this dentro da 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

Essa falha específica de setTimeout já foi resolvida por outros recursos, problemas semelhantes de "perder" this já foram resolvidas criando uma referência explícita ao valor de this no escopo do contexto pretendido. Talvez você veja instâncias de this sendo atribuídas a uma variável usando identificadores como that, self ou _this no bases de código. Essas são convenções de identificadores comuns para variáveis que contêm passou o valor this.

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 de 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 forma a definir o valor de this como undefined ou null, esse valor será substituído por globalThis fora do campo strict modo:

let myFunction = function() {
    console
.log( this );
}

myFunction
.call( null );
> Window {...}

Da mesma forma, se uma função for chamada de uma forma que daria a this um primitivo , esse valor é 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 é forçado para 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 class é usada como um construtor usando o A palavra-chave new, this, refere-se à 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 construtora chamada usando new refere-se 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 de uma função de callback do manipulador de eventos, isso significa 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 do elemento que contém o próprio <button>:

> Button {}

Quando uma arrow function é usada como uma chamada de retorno de listener de eventos, o valor de this é fornecido novamente pelo contexto de execução mais próximo. Na parte superior ou seja, this dentro de uma função de retorno de chamada 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 call(), bind() ou apply() métodos para fazer referência à função de callback de um listener de eventos, 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

No caso de 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?

O objeto undefined
O objeto window
O objeto browser