3 回答

TA貢獻(xiàn)1839條經(jīng)驗(yàn) 獲得超15個(gè)贊
當(dāng)您將函數(shù)分配給單擊處理程序時(shí),將創(chuàng)建一個(gè)閉包。
基本上,當(dāng)您嵌套函數(shù)時(shí)會(huì)形成一個(gè)閉包,內(nèi)部函數(shù)即使在其父函數(shù)已經(jīng)執(zhí)行后,也可以引用其外部封裝函數(shù)中存在的變量。
在執(zhí)行click事件時(shí),處理程序?qū)⒁胕變量具有的最后一個(gè)值,因?yàn)樵撟兞看鎯?chǔ)在閉包中。
如您所見,通過包裝單擊處理程序函數(shù)以接受i變量作為參數(shù),然后返回另一個(gè)函數(shù)(基本上創(chuàng)建另一個(gè)閉包),它可以按預(yù)期工作:
for ( var i = 0; i < 4; i++ ) {
var a = document.createElement( "a" );
a.onclick = (function(j) { // a closure is created
return function () {
alert(j);
}
}(i));
document.getElementById( "foo" ).appendChild( a );
}
迭代時(shí),實(shí)際上創(chuàng)建了4個(gè)函數(shù),每個(gè)函數(shù)i在創(chuàng)建時(shí)(通過傳遞i)存儲(chǔ)對(duì)它的引用,此值存儲(chǔ)在外部閉包中,并在click事件觸發(fā)時(shí)執(zhí)行內(nèi)部函數(shù)。
我使用以下代碼片段解釋閉包(以及curry的一個(gè)非?;镜母拍睿?,我認(rèn)為一個(gè)簡(jiǎn)單的示例可以使該概念更容易理解:
// a function that generates functions to add two numbers
function addGenerator (x) { // closure that stores the first number
return function (y){ // make the addition
return x + y;
};
}
var plusOne = addGenerator(1), // create two number adding functions
addFive = addGenerator(5);
alert(addFive(10)); // 15
alert(plusOne(10)); // 11

TA貢獻(xiàn)2003條經(jīng)驗(yàn) 獲得超2個(gè)贊
無需贅述,這實(shí)際上是通過將實(shí)例變量包裝在立即執(zhí)行的函數(shù)中并將它們傳遞回單擊元素時(shí)將要執(zhí)行的函數(shù)中來創(chuàng)建實(shí)例變量的副本。
這樣想:
function() { alert(i); } // Will expose the latest value of i
(function(I) { return function() { alert(I); }; })(i); // Will pass the current
// value of i and return
// a function that exposes
// i at that time
所以每次循環(huán)過程中,你實(shí)際上是在執(zhí)行一個(gè)返回的函數(shù)功能與當(dāng)前變量的值。
如果您想象自己的循環(huán)中有4個(gè)錨點(diǎn),那么您正在創(chuàng)建4個(gè)獨(dú)立的函數(shù),這些函數(shù)可以可視化為..
function() { alert(0); };
function() { alert(1); };
function() { alert(2); };
function() { alert(3); };
我會(huì)考慮使用javascript來研究范圍和閉包,就好像您走這條路并且不完全了解正在發(fā)生的事情一樣,您可能會(huì)因意外行為而遇到大量問題。

TA貢獻(xiàn)1842條經(jīng)驗(yàn) 獲得超13個(gè)贊
觸發(fā)onclick事件時(shí),將調(diào)用匿名函數(shù),該匿名函數(shù)引用i循環(huán)中使用的相同變量,并保留的最后一個(gè)值(i即4)。
您問題的解決方案是使用返回函數(shù)的函數(shù):
a.onclick = (function(k) {return function() { alert(k); }; })(i);
添加回答
舉報(bào)