2012-10-19 40 views
2

我閱讀倒閉了,我只好很難理解這兩個代碼段之間的區別:這些JS代碼片段如何工作?

var myElements = [ /* DOM Collection */ ]; 

for (var i = 0; i < 100; ++i) { 
    myElements[i].onclick = function() { 
     alert('You clicked on: ' + i); 
    }; 
} 

上面的代碼應該只顯示i 99,每的onclick

function getHandler(n) { 
    return function() { 
     alert('You clicked on: ' + n); 
    }; 
} 

for (var i = 0; i < 100; ++i) { 
    myElements[i].onclick = getHandler(i); 
} 

這上面的代碼爲每個元素點擊事件顯示'i'的正確值!

我不明白爲什麼第一個不顯示正確的值i。如果沒有,爲什麼第二個顯示正確的值?

他們從this link

回答

4

我不明白爲什麼第一個不顯示正確的值i

這是因爲關閉不捕獲i,而是實際的局部變量i。當您繼續更改i的值時,閉包會看到這些更改,因爲它仍在使用相同的變量。

如果沒有,爲什麼第二個顯示正確的值?

因爲在第二個中,閉包捕獲本地變量n,此後永不改變。 (後來調用getHandler有一個完全新的局部變量n;這是非常重要的,而不僅僅是關閉,也爲遞歸支持的功能,否則不同的調用可能會不小心惹了對方的變量!)

0

第99顯示了對各原因,該函數被調用的時候,的i值是99

第二顯示正確的值,因爲你在關閉i(通過參數n)。這意味着雖然i將繼續更改,但n會保留函數被調用時的值。

1

兩者都會在點擊發生時顯示值。

第一個發生點擊時,只有一個i,它是99

在第二個中,每次調用getHandler時都會有一個新的n

0

在第一個示例,在循環中創建onclick函數,並引用i,但直到發生點擊纔會執行該函數。當點擊被觸發時,函數執行,並且讀取i,現在設置爲99.

在第二個示例中,getHandler(i)立即執行,返回一個函數並參考n。(這就是爲什麼返回的函數被稱爲閉包:它已經關閉了傳入的值)。在這個新的函數範圍中,n等於傳入的值 - 您正在查找的值。

0

onclick函數註定要在以後被解僱。

在直到事件被觸發i的值丟失第一種情況下,

但是在第二種情況下我的值複製&保存供以後使用。

0

第二個例子工作的原因,第一個不是與範圍有關。在第一個示例中,變量i存儲在全局範圍內,並在您單擊按鈕時讀取。當你完成循環時,i是99.如果你仍然可以在循環中點擊按鈕1,你將獲得當前值i。 (這是不可能的)。

在第二個示例中,i的副本存儲在函數getHandler中,當您在循環中更改i時,該副本不會更改。 getHandler是您返回的(未命名)函數的範圍,因此它是它讀取的變量。

0

「我」變量綁定到的範圍,您可以創建在目前評估的功能一個新的作用域時,「我」具有正確的價值

可以實現此行爲:

var myElements = [{}, {}]; 

for (var i = 0; i < 2; ++i) { 
    myElements[i].onclick = 
     function(i) { 
      return function() { 
       alert('You clicked on: ' + i); 
      } 
     }(i); // <- This behavior is the important one 
} 

問候