6.1 KiB
title | localeTitle |
---|---|
this reference | esta referência |
this
referência
Em JavaScript, cada função tem um this
de referência criado automaticamente quando você declará-lo. Essa referência é bastante semelhante a this
referência em outras linguagens baseadas em classes, como Java ou C # (JavaScript é uma linguagem baseada em protótipo e nenhum conceito de "classe"): Aponta para qual objeto está chamando a função (esse objeto às vezes chamado como contexto ). No JavaScript, no entanto, this
referência dentro de funções pode ser vinculada a objetos diferentes, dependendo de onde a função está sendo chamada . Aqui estão 5 regras básicas para this
ligação em JavaScript:
Regra 1
Quando uma função é chamada no escopo global, a referência this
é, por padrão, vinculada ao objeto global ( window
no navegador ou global
em Node.js). Por exemplo:
function foo() {
this.a = 2;
}
foo();
console.log(a); // 2
Nota: Se você declarar a foo()
função acima no modo estrito, então você chamar essa função no escopo global, this
será undefined
e atribuição this.a = 2
vai jogar Uncaught TypeError
exceção.
Regra 2
Vamos examinar o exemplo abaixo:
function foo() {
this.a = 2;
}
var obj = {
foo: foo
};
obj.foo();
console.log(obj.a); // 2
Claramente, no trecho acima, a função foo()
está sendo chamada com o contexto obj
e this
referência agora está vinculada ao obj
. Portanto, quando uma função é chamada com um objeto de contexto, a referência this
será vinculada a esse objeto.
Regra 3
.call
, .apply
e .bind
podem ser usados no site de chamadas para vincular explicitamente this
. Usar .bind(this)
é algo que você pode ver em muitos componentes do React.
var foo = function() {
console.log(this.bar)
}
foo.call({ bar: 1 }) // 1
Aqui está um exemplo rápido de como cada um é usado para vincular this
:
.call()
:fn.call(thisObj, fnParam1, fnParam2)
.apply()
:fn.apply(thisObj, [fnParam1, fnParam2])
.bind()
:const newFn = fn.bind(thisObj, fnParam1, fnParam2)
Regra 4
function Point2D(x, y) {
this.x = x;
this.y = y;
}
var p1 = new Point2D(1, 2);
console.log(p1.x); // 1
console.log(p1.y); // 2
A coisa que você deve notar é que a função Point2D
é chamada com a new
palavra-chave, e this
referência está vinculada ao objeto p1
. Portanto, quando uma função é chamada com uma new
palavra-chave, ela criará um novo objeto e this
referência será vinculada a esse objeto.
Nota: Como você chama uma função com uma new
palavra-chave, também a chamamos como função construtora .
Regra 5
JavaScript determina o valor this
em tempo de execução, com base no contexto atual. Então, this
às vezes pode apontar para algo diferente do que você espera.
Considere este exemplo de uma classe Cat com um método chamado makeSound()
, seguindo o padrão da Regra 4 (acima) com uma função construtora e a new
palavra-chave.
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.makeSound(); // Fat Daddy says: Mrrooowww
Agora vamos tentar dar ao gato uma maneira de annoy()
pessoas repetindo seu som 100 vezes, uma vez a cada meio segundo.
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
this.annoy = function() {
var count = 0, max = 100;
var t = setInterval(function() {
this.makeSound(); // <-- this line fails with `this.makeSound is not a function`
count++;
if (count === max) {
clearTimeout(t);
}
}, 500);
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.annoy();
Isso não funciona porque dentro do callback setInterval
nós criamos um novo contexto com escopo global, então this
não aponta mais para a nossa instância do kitty. Em um navegador da Web, this
indicará o objeto Window, que não possui um método makeSound()
.
Algumas maneiras de fazer isso funcionar:
- Antes de criar o novo contexto, atribua
this
a uma variável local chamadame
,self
, ou o que você quiser chamá-lo, e use essa variável dentro do callback.
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
this.annoy = function() {
var count = 0, max = 100;
var self = this;
var t = setInterval(function() {
self.makeSound();
count++;
if (count === max) {
clearTimeout(t);
}
}, 500);
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.annoy();
- Com ES6 você pode evitar atribuir
this
a uma variável local usando uma função de seta, que ligathis
ao contexto do código circundante onde ele está definido.
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
this.annoy = function() {
var count = 0, max = 100;
var t = setInterval(() => {
this.makeSound();
count++;
if (count === max) {
clearTimeout(t);
}
}, 500);
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.annoy();