whatwg - setTimeout y "this" en JavaScript
whatwg español (5)
Me sale un error que dice que method2 no está definido
Sí, cuando this.method de su propietario y pasas la función solo a setTimeout , pierdes la asociación que establece this , por lo que this en method() es igual a la window objeto global.
Consulte esta respuesta para obtener una explicación de la sorprendente manera en que this realmente funciona en JavaScript.
Tengo un método que usa la función setTimeout y realiza una llamada a otro método. En el método de carga inicial 2 funciona bien. Sin embargo, después del tiempo de espera, aparece un error que dice que el method2 no está definido. ¿Qué estoy haciendo mal aquí?
ex:
test.prototype.method = function()
{
//method2 returns image based on the id passed
this.method2(''useSomeElement'').src = "http://www.some.url";
timeDelay = window.setTimeout(this.method, 5000);
};
test.prototype.method2 = function(name) {
for (var i = 0; i < document.images.length; i++) {
if (document.images[i].id.indexOf(name) > 1) {
return document.images[i];
}
}
};
El problema es que setTimeout() hace que javascript use el alcance global. Básicamente, estás llamando a la clase method() , pero no a partir de this . En su lugar, solo le está diciendo a setTimeout que use el method función, sin un alcance particular.
Para solucionarlo, puede ajustar la llamada a la función en otra llamada de función que haga referencia a las variables correctas. Se verá algo como esto:
test.protoype.method = function()
{
var that = this;
//method2 returns image based on the id passed
this.method2(''useSomeElement'').src = "http://www.some.url";
var callMethod = function()
{
that.method();
}
timeDelay = window.setTimeout(callMethod, 5000);
};
that puede ser porque callMethod() encuentra dentro del alcance del método.
Este problema se vuelve más complejo cuando necesita pasar parámetros al método setTimeout , ya que IE no admite más de dos parámetros para setTimeout . En ese caso, deberás leer sobre closures .
Además, como nota al margen, te estás preparando para un ciclo infinito, ya que el method() siempre llama a method() .
Una opción más elegante es agregar .bind(this) al final de su función. P.ej:
setTimeout(function() {
this.foo();
}.bind(this), 1000);
// ^^^^^^^^^^^ <- fix context
Entonces, la respuesta a la pregunta del OP podría ser:
test.prototype.method = function()
{
//method2 returns image based on the id passed
this.method2(''useSomeElement'').src = "http://www.some.url";
timeDelay = window.setTimeout(this.method.bind(this), 5000);
// ^^^^^^^^^^^ <- fix context
};
el this que setTimeOut en setTimeOut está setTimeOut por sí mismo. Crea una var "foo = this;" dentro de su función t est.prototype.method y use foo lugar.
en es6 puedes hacerlo así
window.setTimeout(() => {
this.foo();
}, 1000);