使用閉包和立即執行的方法來保存狀態

// 這個代碼是錯誤的,因爲變量i從來就沒背locked住
// 相反,當循環執行以後,我們在點擊的時候i才獲得數值
// 因爲這個時候i操真正獲得值
// 所以說無論點擊那個連接,最終顯示的都是I am link #10(如果有10個a元素的話)


var elems = document.getElementsByTagName('a');
for (var i = 0; i < elems.length; i++) {
    elems[i].addEventListener('click', function (e) {
        e.preventDefault();
        alert('I am link #' + i);
    }, 'false');
}

// 這個是可以用的,因爲他在自執行函數表達式閉包內部
// i的值作爲locked的索引存在,在循環執行結束以後,儘管最後i的值變成了a元素總數(例如10)
// 但閉包內部的lockedInIndex值是沒有改變,因爲他已經執行完畢了
// 所以當點擊連接的時候,結果是正確的


var elems = document.getElementsByTagName('a');
for (var i = 0; i < elems.length; i++) {
    (function (lockedInIndex) {
        elems[i].addEventListener('click', function (e) {
            e.preventDefault();
            alert('I am link #' + lockedInIndex);
        }, 'false');
    })(i);
}



// 你也可以像下面這樣應用,在處理函數那裏使用自執行函數表達式
// 而不是在addEventListener外部
// 但是相對來說,上面的代碼更具可讀性


var elems = document.getElementsByTagName('a');
for (var i = 0; i < elems.length; i++) {
    elems[i].addEventListener('click', (function (lockedInIndex) {
        return function (e) {
            e.preventDefault();
            alert('I am link #' + lockedInIndex);
        };
    })(i), 'false');

}

//也可以用閉包來保存狀態

var elems = document.getElementsByTagName('a');
function keep(i){
 var keep = i;
 return function(){
   alert(keep);
 }
}
for (var i = 0; i < elems.length; i++) {
   var index
    elems[i].addEventListener('click', keep(i), 'false');
}



不管那種方法,關鍵是看最後方法執行時是調用的哪個變量,第一種直接調用i,i是對外面可見的,所以在for後會變化,而另外三種都是調用的非i變量,而且這個非i變量在for中是不可見的,無法改變!!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章