2011-06-06 102 views
6

考慮的JavaScript的這個小片斷:如何解決Javascript關閉問題?

for(var i in map.maps) 
{ 
    buttons.push($("<button>").html(i).click(function() { alert(i); })); 
} 

它創建用於每個在map.maps對象中的字段中的一個按鈕(這是一個ASSOC數組)。我將索引設置爲按鈕的文本,並將其設置爲提醒索引。很顯然,人們會希望所有按鈕在單擊時都會提醒它自己的文本,但是當單擊時,所有按鈕都會提醒map.maps對象中最終索引的文本。

我認爲這種行爲是由整潔的方式引起的,JavaScript處理關閉,返回並從創建它們的閉包執行函數。

我可以想象得到解決這個問題的唯一方法是將索引設置爲按鈕對象上的數據,並從點擊回調中使用它。我也可以模仿我的buttons對象中的map.maps索引,並使用indexOf找到正確的點擊索引,但我更喜歡前一種方法。

我在尋找的答案是確認,我正在做它正確的方式,或建議如何我做到這一點。

+1

[我如何將JS變量的值(不是引用)傳遞給函數]幾乎完全重複?(http://stackoverflow.com/questions/2568966/how-do-i-pass-the -value-not-the-reference-of-js-variable-to-a-function) – 2011-06-06 09:04:35

回答

9

擁抱關閉,不解決它們。

for(var i in map.maps) 
{ 
    (function(i){ 
     buttons.push($("<button>").html(i).click(function() { alert(i); })); 
    })(i); 
} 

你需要用一個使用VAR我,以便它在一個單獨的封閉結束和值保持在該關閉一個局部變量/參數的代碼。

在lonesomeday的回答中使用一個單獨的函數隱藏了這個閉包行爲,但同時更清晰。

+0

我的代碼速度很快,因爲函數只創建一次。但是,效果完全相同。 – lonesomeday 2011-06-06 11:23:49

4

如果你通過了變更值的另一個函數作爲參數,該值將被鎖定在:

function createButton(name) { 
    return $("<button>").html(name).click(function() { alert(name); }); 
} 

for (var i in map.maps) { 
    buttons.push(createButton(i)); 
} 
0

這是最優雅的方式做你想做什麼:

var buttons = myCharts.map(function(chart,i) { 
    return $("<button>").html(chart).click(function(event){ 
     alert(chart); 
    }); 
} 

需要關閉在JavaScript代碼優雅,並且不應該解決它們。否則,你不能做像嵌套for循環(沒有可怕的黑客)。當你需要關閉時,使用關閉。不要害怕在函數內部定義新的函數。

1
for(var i in map.maps){ 
    (function(i){ 
     buttons.push($("<button>").html(i).click(function() { alert(i); })) 
    })(i); 
} 

爲什麼封你的情況失敗的原因是,它的功能被綁定後,也這是在這種情況下是事件處理仍在更新值。這是由於閉包只記住對變量的引用,而不是綁定時的實際值。

通過執行匿名函數,您可以執行正確的值,這通過將我傳遞給匿名函數來實現,因此,然後在匿名函數的範圍內我被重新定義。