2012-05-13 5 views
6

Chcę przekazać argument do funkcji o nazwie przy użyciu setTimeout. Znalazłem te trzy opcje:Jak przekazać argument do funkcji o nazwie 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); } 

To pokazuje 2, undefined i 1 w programie Internet Explorer 9.

Metoda 1: Oczywiście, nie chciałbym argument zostać zmienione po minięciu go (oczywiście w przypadku prostych liczb całkowitych).

Metoda 2: Byłoby idealnie, gdyby obsługiwany był tylko Internet Explorer.

Metoda 3: To wydaje się być jedynym wyborem. Ale wydaje się raczej mniej ładny niż inne, przekazując coś do oceny, a nie funkcję.

Czy istnieje lepszy sposób?

+2

metoda 3 jest tym, który powinien **nigdy nie używaj. A metoda 2 jest przestarzała nawet w przeglądarkach gecko - więc nawet bez wsparcia IE nie jest to łatwe. – ThiefMaster

Odpowiedz

7

Najlepszym rozwiązaniem mogę myśleć korzysta bind():

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

Ponieważ bind() faktycznie jest wywołanie funkcji, odczytuje bieżącą wartość A i zwraca wartość funkcji z tym związany jako argument. Jeśli okaże się, że trudno zrozumieć, spróbuj tego:

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

Zauważ, że this niby tu leżeć - można bezpiecznie przechodzić window również.


Pierwsza metoda jest również dopuszczalne, to po prostu musi być nieznacznie poprawiła:

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

Co obserwujemy w rzeczywistości jest cechą, a nie bug. Przechodzisz zamknięcie do zmiennej lokalnej odwołującej się do setTimeout(). JavaScript jest na tyle sprytny, by opóźnić dostęp do tej zmiennej do momentu, w którym funkcja jest faktycznie wywoływana. A ponieważ zmodyfikowałeś zmienną, zobaczysz najnowszą wersję.


Druga metoda jest przestarzała nie będzie działać w każdej przeglądarce.


Trzecia metoda jest straszna, unikać przechodzenia ciąg setTimeout(), zawsze jest lepszym rozwiązaniem.

+0

Istnieją także rozwiązania 'whatsA.apply (this, [A])' oraz 'whatsA.call (this, A)'. – VisioN

+0

+1 dla czystego rozwiązania '.bind()'. @VisionN: Te wersje wymagałyby funkcji samo wywołania, aby uniknąć zamknięcia przez zmienną. – ThiefMaster

+0

* możesz bezpiecznie przekazać także okno * - lub 'null', które jest czystsze IMHO. – ThiefMaster

4

Można użyć Zamknięcie:

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

+1 Naprawdę fajny pomysł! – VisioN

0

twoich trzech metod:

Wariant 1:

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

Ten działa wszędzie i jest prosta.Polecam, chyba że zmienna A może się zmienić przed wywołaniem funkcji setTimeout. Jeśli chcesz zamrozić wartość A, zobacz moją opcję 4 poniżej.


Opcja 2:

setTimeout(whatsA, 100, A);

Zadziała tylko w niektórych przeglądarkach. Niepolecane.


Wariant 3:

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

To nigdy nie jest zalecane. Zbudowanie kodu jako ciągu znaków i późniejsza ocena jest prawie nigdy najlepszym rozwiązaniem.


Polecam Wariant 4:

Aby zamrozić wartość A można tworzyć zamknięcie przy użyciu siebie funkcję wykonywania:

A = 1; 

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

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