Frequentemente precisamos definir um setTimeout()
ou setInterval()
dentro de um escopo especial como uma determinada classe. A função setTimeout()
/ setInterval()
deve chamar um método privilegiado ou público de uma determinada classe e a this
palavra-chave de acesso a . Muitas vezes as pessoas ainda tentam iniciar um tempo limite / intervalo usando o seguinte e não têm sucesso com isso:
Errado:
function myCounter() {
this.i = 0;
this.init();
}
myCounter.prototype.init = function() {
setInterval(this.countUp,500); // fails
setInterval(function() { this.countUp(); }, 500); // also fails, this is in a different scope
};
myCounter.prototype.countUp = function() {
this.i++;
document.getElementById('counter').innerHTML = this.i;
};
O exemplo acima está totalmente correto, exceto para chamar a função dentro do loop. Não é possível usar this.counUp () dentro de outro escopo, não está mais relacionado à classe desejada, assim que é disparado. Portanto, temos que conectar uma variável ao nosso escopo atual, definindo uma nova variável e atribuindo this
a ela. Fe Isso vai funcionar. Mesmo na função chamada, funcionará bem já que estamos no escopo correto de nossa classe. Agora, um exemplo prático:var _this = this; setInterval(function() { _this.countUp(); }, 500);
this
Corrigir:
// basic class implementation
function myCounter() {
// privileged property for iteration
this.i = 0;
// privileged init method
this.init();
}
// defining init method
myCounter.prototype.init = function () {
// reassign this
var _this = this;
setInterval(function () {
// call this.countUp() using our new created variable.
// this has to be done as this would normally call something
// inside this function, so we have to pass it as own
// variable over
_this.countUp();
}, 500);
};
// defining the counter method
myCounter.prototype.countUp = function () {
this.i++;
document.getElementById('counter').innerHTML = this.i;
};
// create a new instance of our counter class
var counter = new myCounter();
Correto # 2:
Outro exemplo de trabalho é o uso do método ECMAScript5s, bind(this, [arg1, arg2, arg3])
que nos permite vincular argumentos a uma função, no nosso caso, estamos ignorando this
. Esta é a maneira mais avançada de fazer isso, mas também tenha em mente que essa função ainda é bastante nova e não é tão amplamente suportada como a primeira maneira de fazer isso. Você pode dar uma olhada na tabela de compatibilidade na parte inferior da seguinte página: tabela de compatibilidade bind () . Tudo o que temos a fazer é atribuir a função desejada dentro do tempo limite / intervalo da seguinte forma, setInterval(this.countUp.bind(this), 500);
é isso! Pedaço de bolo, não é? 🙂 Agora, um exemplo prático:
// basic class implementation
function myCounter() {
// privileged property for iteration
this.i = 0;
// privileged init method
this.init();
}
// defining init method
myCounter.prototype.init = function () {
setInterval(
// we can also use bind() to assign the correct scope
this.countUp.bind(this)
, 500);
};
// defining the counter method
myCounter.prototype.countUp = function () {
this.i++;
document.getElementById('counter').innerHTML = this.i;
};
// create a new instance of our counter class
var counter = new myCounter();