2009-01-15 59 views
2

看來我不明白JavaScript回調和我想的一樣。java和javascript回調比較

在下面的例子中,我認爲setTimeout中的每個函數副本都會引用它自己的變量「index」副本。因此,運行示例應該會產生以下警報:「零」「一」「兩」「。

var array = ["zero", "one", "two"]; 
var out = ""; 
for(var i = 0; i < 3; i++){ 
    var index = i; 
    setTimeout( function(){alert(array[index])}, 1); 
} 

然而,似乎那裏有索引變量的只有一個副本,並且回調函數點的同一個變量的所有副本,給我下面的提醒:「兩節」「兩會」「兩節」。

java中的以下analagous(我認爲)示例打印出「zero」「one」「two」,如預期的那樣。

import java.util.ArrayList; 
import java.util.List; 


public class CallBacks { 

    public static void main(String[] args) { 

    String[] array = {"zero", "one", "two"}; 
    List<Callback> callBacks = new ArrayList<Callback>(); 
    for(int i = 0; i<3; i++){ 
     final String print = array[i]; 
     callBacks.add(
       new Callback(){ 
       public void execute(){ 
        System.out.println(print); 
       } 
       } 
    ); 
    } 
    for(Callback cb : callBacks){ 
     cb.execute(); 
    } 
    } 

    private interface Callback{ 
    public void execute(); 
    } 

} 

任何人都可以向我解釋爲什麼JS例子不起作用,也許比較兩個例子中發生了什麼?

+0

你見過:http://stackoverflow.com/questions/442985/how-can-one-de-reference-javascript-variables-when-enclosing-an-outer-scope – Prestaul 2009-01-15 15:22:03

+0

Prestaul,謝謝,這幾乎是我的同一個問題。我在發佈之前查找了類似的問題,但沒有找到這個問題。 – morgancodes 2009-01-15 15:50:46

+0

昨天我問了一個幾乎相同的問題,並在答案中得到了幾個不同的變化,並且討論了每個問題的優點。可能是值得一試 [1]:http://stackoverflow.com/questions/442985/how-can-one-de-reference-javascript-variables-when-enclosing-an-outer-scope – meouw 2009-01-15 16:08:17

回答

1

index隨循環的每次迭代而改變。你需要的是放置index到不受環路封閉:

var array = ["zero", "one", "two"]; 
var out = ""; 
for(var i = 0; i < 3; i++) { 
    (function(index) { 
     setTimeout( function(){alert(array[index])}, 1); 
    })(i) 
} 
1

JavaScript中的for循環沒有它自己的範圍 - 讓你在循環中創建一個變種是不是從一個外部定義不同的。

0

Private Members In JavaScript是我最喜歡的封閉參考。它被寫爲在JS對象中提供私有變量的方法(可能有用,也許不是),但是在這個過程中通過一個關於閉包如何工作的良好介紹,特別是在JS中。

The comp.lang.javascript FAQ還有一個值得關閉的部分。

關閉可能會令人困惑,所以我把放在Rhino書中的working example of the shortest useful closure I've come across,放在一起。

哦,我還沒有足夠的代表評論:)但我看到你的問題上面有關你爲什麼有時必須放在括號括起來。這隻有當你調用一個匿名函數內聯。例如在這裏需要括號:

(function (arg) {alert(arg);})('hi world'); 

因爲要創建一個函數,然後立即調用它。但是在通常的情況下,你只需要聲明一個命名函數供以後使用就不需要這些parens。