setTimeout e “this” in JavaScript

Ho un metodo che utilizza la funzione setTimeout e effettua una chiamata a un altro metodo. Nel metodo di caricamento iniziale 2 funziona correttamente. Tuttavia, dopo il timeout, viene visualizzato un errore method2 che method2 non è definito. Cosa sto facendo di sbagliato qui?

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  1) { return document.images[i]; } } }; 

Il problema è che setTimeout() fa sì che javascript usi l’ambito globale. In sostanza, stai chiamando la class method() , ma non da this . Invece stai dicendo a setTimeout di usare il method della funzione, senza alcun ambito particolare.

Per risolvere questo problema è ansible racchiudere la chiamata di funzione in un’altra chiamata di funzione che fa riferimento alle variabili corrette. Sembrerà qualcosa del genere:

 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 può essere dovuto callMethod() fatto che callMethod() è nell’ambito del metodo.

Questo problema diventa più complesso quando è necessario passare i parametri al metodo setTimeout , poiché IE non supporta più di due parametri per setTimeout . In tal caso dovrai leggere le chiusure .

Inoltre, come sidenote, ti stai impostando per un ciclo infinito, poiché method() chiama sempre method() .

Un’opzione più elegante è quella di aggiungere .bind(this) alla fine della tua funzione. Per esempio:

  setTimeout(function() { this.foo(); }.bind(this), 1000); // ^^^^^^^^^^^ < - fix context 

Quindi la risposta alla domanda dell'OP potrebbe essere:

  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 }; 

il this hai usato in setTimeOut è lo scoping via sé stesso. Crea una var "foo = this;" all’interno della tua funzione est.prototype.method e usa invece foo .

Ottengo un errore che dice che method2 non è definito

Sì, quando si this.method dal suo proprietario e si passa la funzione da solo a setTimeout , si perde l’associazione che lo imposta, quindi this in method() è uguale alla window dell’object globale.

Vedi questa risposta per una spiegazione del modo sorprendente in cui this funziona effettivamente in JavaScript.

in es6 puoi farlo in questo modo

 window.setTimeout(() => { this.foo(); }, 1000);