2012-05-13 12 views
6

Voglio passare un argomento a una funzione chiamata utilizzando setTimeout. Ho trovato queste tre opzioni:Come posso passare un argomento a una funzione chiamata usando setTimeout?

A = 1; 
// Method 1: closure things 
setTimeout(function() { whatsA(A); }, 100); 
// Method 2: third argument (same result with [A]) 
setTimeout(whatsA, 100, A); 
// Method 3: eval 
setTimeout('whatsA(' + A + ')', 100); 
A = 2; 
function whatsA(X) { console.log(X); } 

Questo dimostra 2, undefined e 1 in Internet Explorer 9.

Metodo 1: Chiaramente, non vorrei l'argomento di essere cambiato dopo il superamento di esso (certamente nel caso di numeri interi semplici).

Metodo 2: Ciò sarebbe perfetto se solo Internet Explorer lo supportasse.

Metodo 3: questa sembra essere l'unica scelta. Ma sembra piuttosto meno carino degli altri, passando qualcosa da valutare piuttosto che una funzione.

C'è un modo migliore?

+2

Metodo 3 è quello che si dovrebbe ** mai ** usare. E il Metodo 2 è deprecato anche nei browser gecko - quindi anche senza supportare IE è praticamente impossibile. – ThiefMaster

risposta

7

La soluzione migliore che posso pensare sta usando bind():

A = 1; 
setTimeout(whatsA.bind(this, A), 100); 

Perché bind() è in realtà una funzione di invocazione, si legge il valore corrente A e restituisce una funzione con quel valore legato come un argomento. Se si fatica a capire, provare questo:

var newFun = whatsA.bind(this, 42); 
newFun() 

noti che this è una specie di una bugia qui - è possibile passare in modo sicuro window pure.


Il primo metodo è anche accettabile, ha solo bisogno di essere leggermente migliorata:

A = 1; 
var tmpA = A; 
setTimeout(function() { whatsA(tmpA); }, 100); 

cosa si sta osservando è in realtà una caratteristica, non un bug. Stai passando una chiusura a setTimeout() facendo riferimento alla variabile locale. JavaScript è abbastanza intelligente da ritardare l'accesso a quella variabile fino al momento in cui la funzione viene effettivamente chiamata. E dal momento che hai modificato la variabile, vedi la versione più recente.


Il secondo metodo è deprecato non funziona in qualsiasi browser.


terzo metodo è terribile, evitare di passare stringa da setTimeout(), c'è sempre una soluzione migliore.

+0

Ci sono anche le soluzioni 'whatsA.apply (this, [A])' e 'whatsA.call (this, A)'. – VisioN

+0

+1 per la soluzione pulita '.bind()'. @VisionN: Quelle versioni richiederebbero la funzione di auto-chiamata per evitare di chiudere la variabile. – ThiefMaster

+0

* puoi tranquillamente passare anche la finestra * - o 'null' che è IMHO più pulito. – ThiefMaster

4

Si potrebbe utilizzare chiusura:

setTimeout((function(A){ 
       return function(){ 
        whatsA(A); 
       }; 
      })(A), 100); 
+0

+1 Davvero una bella idea! – VisioN

0

dei tre metodi:

Opzione 1:

setTimeout(function() { whatsA(A); }, 100);

questo funziona in tutto il mondo ed è semplice.È quello che consiglierei a meno che la variabile A non cambi prima che venga chiamata la funzione setTimeout. Se è necessario bloccare il valore di A, consultare la mia opzione 4 di seguito.


Opzione 2:

setTimeout(whatsA, 100, A);

Questo funziona solo in alcuni browser. Non consigliato.


Opzione 3:

setTimeout('whatsA(' + A + ')', 100);

Questo non è mai consigliato. Costruire il codice come una stringa e quindi valutarlo in seguito non è quasi mai la soluzione migliore.


Suggerirei Opzione 4:

di congelare il valore di A, è possibile creare una chiusura utilizzando una funzione di esecuzione di auto:

A = 1; 

function(A) { 
    setTimeout(function() {whatsA(A);}, 100); 
}(A); 

A = 2; 
function whatsA(X) { console.log(X); } 
Problemi correlati