2010-02-03 65 views
12

循環中的閉合件導致了我的問題。我想我不得不做另一個函數來返回一個函數來解決這個問題,但我不能讓它與我的jQuery代碼一起工作。for循環中的閉合件

這裏是一個簡化形式的基本問題:

function foo(val) { 
    alert(val); 
} 

for (var i = 0; i < 3; i++) { 
    $('#button'+i).click(function(){ 
    foo(i); 
    }); 
} 

自然地點擊任何三個按鈕將給予警告說3.我想要的功能是,點擊按鈕1會給出一個警告說1,按鈕2會說2等。

我該如何做到這一點?

回答

10

查看bind方法。

$('#button'+i).bind('click', {button: i}, function(event) { 
    foo(event.data.button); 
}); 

從文檔:

可選EVENTDATA參數 不常用。當提供時,這個 參數允許我們將其他 信息傳遞給處理程序。一個方便 使用這個參數是工作 各地引起關閉問題

+0

謝謝,它的工作原理。 – Rob 2010-02-03 14:16:56

+0

也爲我工作! – bychkov 2011-03-24 21:02:46

+0

+1,解決我的問題 – anvd 2011-12-12 16:04:27

3

使用jQuery的距離。每個的功能 - 我猜你一個循環,通過類似的元素 - 所以使用類似添加點擊:

$(element).children(class).each(function(i){ 
    $(this).click(function(){ 
     foo(i); 
    }); 
}); 

未經測試,但我總是儘可能使用這種結構。

1

或者只是製造一個新的功能,如你所描述的。它應該是這樣的:

function foo(val) { 
    return function() { 
     alert(val); 
    } 
} 

for (var i = 0; i < 3; i++) { 
    $('#button'+i).click(foo(i)); 
} 

我敢肯定邁赫達德的解決方案是行不通的。當你看到人們複製到一個臨時變量時,通常會將「this」的值保存在內部子範圍內。

+0

是的,他的解決方案沒有工作,我認爲他刪除了它。 – Rob 2010-02-03 14:13:36

+0

這是我所知道的最佳答案。帶綁定的代碼很好,但該數據參數實際上是一個醜陋的黑客。這種方法的優點是,無論何時出現此問題(創建引用循環變量的閉包),它都可以工作,無論您是否擁有jQuery。 – 2010-02-03 14:27:06

+0

@Jason:雖然我同意這是一個偉大的答案,當然如果jQuery的沒有提到和標籤的問題,我會給出了答案,我不同意它是一個「醜陋的黑客攻擊」 - 這當然整潔。此外,半類似'Function.bind'是在第5版規範,所以你可以說爲純醇」 JS最好的答案將是等效的原型法,將提供在JS的當前版本該功能。 http://snipplr.com/view/13987/functionbind/只是我能找到的一個例子,我知道有很多。 – 2010-02-03 14:48:41

5

@Andy解決方案是最好的。但是你也可以使用Javascript範圍來幫助你保存閉包中的值。

您可以通過執行匿名函數在循環體中創建一個新的作用域來實現。

for (var i = 0; i < 3; i++) { 
    (function(){ 
    var index = i; 
    $('#button'+index).click(function(){ 
     foo(index); 
    }); 
    })(); 
} 

由於環體是在每次迭代一個新的範圍,索引變量被複制以在每次迭代時正確的值。

+0

由於這是很有必要知道 – Rob 2010-02-03 14:19:30

6

試試這個代碼:

function foo(val) { 
    alert(val); 
} 

var funMaker = function(k) { 
    return function() { 
    foo(k); 
    }; 
}; 

for (var i = 0; i < 3; i++) { 
    $('#button'+i).click(funMaker(i)); 
} 

一些重要的點這裏:

  • JavaScript是函數作用域。如果你想要一個新的('更深')範圍,你需要創建一個函數來保存它。
  • 這個解決方案是Javascript特定的,它可以使用或不使用jQuery。
  • 解決方案的工作,因爲i每個值在一個新的範圍被複製爲k,和從funMaker返回的函數關閉圍繞k(其不存在於循環變化),而不是圍繞i(它)。
  • 您的代碼不起作用,因爲您傳遞給click的函數不是「擁有」i,它關閉了其創建者的i,並且i更改了循環。
  • 的例子可能已經寫有funMaker內聯,但我通常使用這些輔助功能,使事情更加清楚。
  • funMaker的說法是k,但這沒什麼區別,它可能是i沒有任何問題,因爲它存在於功能funMaker的範圍內。
  • 「環境」評估模型最清晰的解釋之一可以在Sussman的「計算機程序的結構和解釋」中找到,Abelson(http://mitpress.mit.edu/sicp/全文在線提供,不是一個簡單的閱讀) - 參見3.2節。由於JavaScript實際上是C語言的Scheme,所以這個解釋是可以的。

編輯:修正了一些標點符號。

+0

同爲darkporter的答案,但也有一些很好的闡述。 *「JavaScript實際上是C語言的Scheme」*每次有人第一次理解這個時,JS天使就會得到他的翅膀。 – 2010-02-03 14:41:46