和普通function執行的時候傳參數一樣,自執行的函數表達式也可以這麼傳參,因爲閉包直接可以引用傳入的這些參數,利用這些被lock住的傳入參數,自執行函數表達式可以有效地保存狀態。
// 這個代碼是錯誤的,因爲變量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'); }
其實,上面2個例子裏的lockedInIndex變量,也可以換成i,因爲和外面的i不在一個作用於,所以不會出現問題,這也是匿名函數+閉包的威力。
該內容是深入理解JavaScript系列(4):立即調用的函數表達式 中的一部分。