Resumo : neste tutorial, você aprenderá sobre o this
valor do JavaScript e o compreenderá claramente em vários contextos.
Se você trabalha com outras linguagens de programação, como Java, C# ou PHP , já está familiarizado com a this
palavra-chave.
Nessas linguagens, a this
palavra-chave representa a instância atual da classe e só é relevante dentro da classe.
JavaScript também possui this
palavra-chave. No entanto, a this
palavra-chave em JavaScript se comporta de maneira diferente de outras linguagens de programação.
Em JavaScript, você pode usar a this
palavra-chave nos contextos global e de função . Além disso, o comportamento da this
palavra-chave muda entre os modos estrito e não estrito.
Qual é esta palavra-chave
Em geral, this
faz referência ao objeto do qual a função é uma propriedade. Em outras palavras, faz this
referência ao objeto que está chamando a função no momento.
Suponha que você tenha um objeto counter
que possua um método next()
. Ao chamar o next()
método, você pode acessar o this
objeto.
let counter = {
count: 0,
next: function () {
return ++this.count;
},
};
counter.next();
Linguagem de código: JavaScript ( javascript )
Dentro da next()
função, faz this
referência ao counter
objeto. Veja a seguinte chamada de método:
counter.next();
Linguagem de código: CSS ( css )
A next()
é uma função que é propriedade do counter
objeto. Portanto, dentro da next()
função, faz this
referência ao counter
objeto.
Contexto global
No contexto global, faz this
referência ao objeto global , que é o window
objeto no navegador da web ou global
objeto no Node.js.
Esse comportamento é consistente nos modos estrito e não estrito. Aqui está a saída no navegador da web:
console.log(this === window); // true
Linguagem de código: JavaScript ( javascript )
Se você atribuir uma propriedade ao this
objeto no contexto global, o JavaScript adicionará a propriedade ao objeto global conforme mostrado no exemplo a seguir:
this.color= 'Red';
console.log(window.color); // 'Red'
Linguagem de código: JavaScript ( javascript )
Contexto da função
Em JavaScript, você pode chamar uma função das seguintes maneiras:
- Invocação de função
- Invocação de método
- Invocação do construtor
- Invocação indireta
Cada invocação de função define seu próprio contexto. Portanto, o this
se comporta de maneira diferente.
1) Invocação de função simples
No modo não estrito, faz this
referência ao objeto global quando a função é chamada da seguinte forma:
function show() {
console.log(this === window); // true
}
show();
Linguagem de código: JavaScript ( javascript )
Quando você chama a show()
função, ela this
faz referência ao objeto global , que está no window
navegador da web e global
no Node.js.
Chamar a show()
função é o mesmo que:
window.show();
Linguagem de código: JavaScript ( javascript )
No modo estrito, o JavaScript define o this
interior de uma função como undefined
. Por exemplo:
"use strict";
function show() {
console.log(this === undefined);
}
show();
Linguagem de código: JavaScript ( javascript )
Para ativar o modo estrito, você usa a diretiva "use strict"
no início do arquivo JavaScript. Se você deseja aplicar o modo estrito apenas a uma função específica, coloque-o no topo do corpo da função.
Observe que o modo estrito está disponível desde ECMAScript 5.1. O strict
modo se aplica a funções e funções aninhadas. Por exemplo:
function show() {
"use strict";
console.log(this === undefined); // true
function display() {
console.log(this === undefined); // true
}
display();
}
show();
Linguagem de código: JavaScript ( javascript )
Saída:
true
true
Linguagem de código: JavaScript ( javascript )
Na display()
função interna, this
também definido undefined
como mostrado no console.
2) Invocação de método
Quando você chama um método de um objeto, o JavaScript define this
o objeto que possui o método. Veja o seguinte car
objeto:
let car = {
brand: 'Honda',
getBrand: function () {
return this.brand;
}
}
console.log(car.getBrand()); // Honda
Linguagem de código: JavaScript ( javascript )
Neste exemplo, o this
objeto no getBrand()
método faz referência ao car
objeto.
Como um método é uma propriedade de um objeto que é um valor, você pode armazená-lo em uma variável.
let brand = car.getBrand;
Linguagem de código: JavaScript ( javascript )
E então chame o método através da variável
console.log(brand()); // undefined
Linguagem de código: JavaScript ( javascript )
Você obtém undefined
em vez de "Honda"
porque quando você chama um método sem especificar seu objeto, o JavaScript define this
o objeto global no modo não estrito e undefined
no modo estrito.
Para corrigir esse problema, você usa o bind()
método do Function.prototype
objeto. O bind()
método cria uma nova função cuja this
palavra-chave é definida com um valor especificado.
let brand = car.getBrand.bind(car);
console.log(brand()); // Honda
Linguagem de código: JavaScript ( javascript )
Neste exemplo, quando você chama o brand()
método, a this
palavra-chave está vinculada ao car
objeto. Por exemplo:
let car = {
brand: 'Honda',
getBrand: function () {
return this.brand;
}
}
let bike = {
brand: 'Harley Davidson'
}
let brand = car.getBrand.bind(bike);
console.log(brand());
Linguagem de código: JavaScript ( javascript )
Saída:
Harley Davidson
Neste exemplo, o bind()
método define the this
para o bike
objeto, portanto, você vê o valor da brand
propriedade do bike
objeto no console.
3) Invocação do construtor
Ao usar a new
palavra-chave para criar uma instância de um objeto de função, você usa a função como construtor.
O exemplo a seguir declara uma Car
função e a invoca como construtor:
function Car(brand) {
this.brand = brand;
}
Car.prototype.getBrand = function () {
return this.brand;
}
let car = new Car('Honda');
console.log(car.getBrand());
Linguagem de código: JavaScript ( javascript )
A expressão new Car('Honda')
é uma invocação do construtor da Car
função.
JavaScript cria um novo objeto e define this
o objeto recém-criado. Esse padrão funciona muito bem com apenas um problema potencial.
Agora, você pode invocar Car()
como uma função ou como um construtor. Se você omitir a new
palavra-chave da seguinte forma:
var bmw = Car('BMW');
console.log(bmw.brand);
// => TypeError: Cannot read property 'brand' of undefined
Linguagem de código: JavaScript ( javascript )
Desde o this
valor nos Car()
conjuntos até o objeto global, o bmw.brand
retorno é undefined
.
Para garantir que a Car()
função seja sempre invocada usando a invocação do construtor, adicione uma verificação no início da Car()
função da seguinte maneira:
function Car(brand) {
if (!(this instanceof Car)) {
throw Error('Must use the new operator to call the function');
}
this.brand = brand;
}
Linguagem de código: JavaScript ( javascript )
ES6 introduziu uma metapropriedade chamada new.target
que permite detectar se uma função é invocada como uma invocação simples ou como um construtor.
Você pode modificar a Car()
função que usa a new.target
metapropriedade da seguinte maneira:
function Car(brand) {
if (!new.target) {
throw Error('Must use the new operator to call the function');
}
this.brand = brand;
}
Linguagem de código: JavaScript ( javascript )
4) Invocação Indireta
Em JavaScript, as funções são cidadãs de primeira classe . Em outras palavras, funções são objetos, que são instâncias do tipo Function .
O Function
tipo possui dois métodos: call()
e apply()
. Esses métodos permitem definir o this
valor ao chamar uma função. Por exemplo:
function getBrand(prefix) {
console.log(prefix + this.brand);
}
let honda = {
brand: 'Honda'
};
let audi = {
brand: 'Audi'
};
getBrand.call(honda, "It's a ");
getBrand.call(audi, "It's an ");
Linguagem de código: JavaScript ( javascript )
Saída:
It's a Honda
It's an Audi
Linguagem de código: PHP ( php )
Neste exemplo, chamamos a getBrand()
função indiretamente usando o call()
método da getBrand
função. Passamos honda
e audi
object como primeiro argumento do call()
método, portanto, obtivemos a marca correspondente em cada chamada.
O apply()
método é semelhante ao call()
método, exceto que seu segundo argumento é uma matriz de argumentos.
getBrand.apply(honda, ["It's a "]); // "It's a Honda"
getBrand.apply(audi, ["It's an "]); // "It's a Audi"
Linguagem de código: JavaScript ( javascript )
Funções de seta
ES6 introduziu um novo conceito chamado função de seta . Nas funções de seta, o JavaScript define o this
lexicamente.
Isso significa que a função de seta não cria seu próprio contexto de execução , mas herda o this
da função externa onde a função de seta está definida. Veja o exemplo a seguir:
let getThis = () => this;
console.log(getThis() === window); // true
Linguagem de código: JavaScript ( javascript )
Neste exemplo, o this
valor é definido para o objeto global, ou seja, window
no navegador da web.
Como uma função de seta não cria seu próprio contexto de execução, definir um método usando uma função de seta causará um problema. Por exemplo:
function Car() {
this.speed = 120;
}
Car.prototype.getSpeed = () => {
return this.speed;
};
var car = new Car();
console.log(car.getSpeed()); // 👉 undefined
Linguagem de código: JavaScript ( javascript )
Dentro do getSpeed()
método, o this
valor faz referência ao objeto global, não ao Car
objeto, mas o objeto global não possui uma propriedade chamada velocidade. Portanto, o this.speed
no getSpeed()
método retorna undefined
.