我正在使用JQuery和jsTree,並且我遇到了關於閉包如何工作的一些混淆。關閉Javascript關閉的問題
我有一個具有.jsTree成員和.populateTree方法的對象。該方法用一個字符串數組來調用,它應該創建jsTree的節點。
jsTree構建一個樹形控件,其中每個節點都有一個錨點「」,其中包含節點的文本。我想單擊文本切換節點打開或關閉,就像單擊樹中的+/-按鈕一樣。所以我試圖添加一個click()函數來做到這一點,並且我得到了意想不到的行爲。
所以,這裏是代碼:
populateTree: function populateTree(nodeNames)
{
if (!this.jsTree) // Note 1
return;
var me = this; // Note 2
for (var i = 0; i < nodeNames.length; i++)
{
var nodeName = nodeNames[i];
var node = this.jsTree.create_node(-1, "last", { state: 'open', data: nodeName }); //Note 3
this.jsTree.create_node(node, "last", { data: "child one" }); // Note 4
this.jsTree.create_node(node, "last", { data: "child two" });
this.jsTree.create_node(node, "last", { data: "child three" });
var anchor = node.find("a"); // Note 5
anchor.click(function() { me.jsTree.toggle_node(node); }); // Note 6
}
},
注1:這是一個JavaScript對象的成員函數,所以當它被稱爲「這種」指向的對象。該對象包含一個jsTree成員變量,該變量應該已經被初始化爲包含一個jsTree對象,沒有節點。
注2:我們是在注6定義一個「點擊」功能,而被調用時,「這」不會指向包含jsTree的對象,所以我們保存在「本」名爲「me」的變量,它將在執行「click」函數時處於範圍內,因爲創建該函數會創建一個閉包,該閉包包含對函數定義時範圍內的所有變量的引用。
注3:對於數組中的每個元素,我們創建一個頂級節點(父節點爲-1)。
注4:對於我們創建的每個頂級節點,我們創建三個子節點。
注意5:每個節點都包含一個錨元素(「」),這就是我們想要附加一個「點擊」功能。
注意6:在「click」函數中,「me」應指向包含樹的對象(請參見注釋2),並且「節點」應該指向剛剛創建的節點,電流通過迴路(見注3)。
我的問題?無論我點擊哪個錨點,它始終是打開和關閉的最後一個頂級節點。就像我們創建的每個「click」函數的閉包都有一個只引用最後一個「節點」變量的閉包。這不是我認爲閉包工作的方式。
有人能幫助我理解我的理解出錯的地方嗎?
謝謝。
另外一個澄清一點:JavaScript語句塊(你的「for」循環的花括號塊)做**不**創建自己的詞彙範圍。它與C++或Java等語言不同。只有函數創建新的範圍。 – Pointy 2011-03-31 16:06:43
如[這個問題]提到你有完全相同的問題(http://stackoverflow.com/questions/341723/event-handlers-inside-a-javascript-loop-need-a-closure)。請參閱已接受的答案解決方案 – schellmax 2011-03-31 16:04:06