了解臭名昭著的JavaScript 循環問題
在JavaScript 中,使用循環生成元素並將其綁定到事件處理程序時會出現常見問題。下面的程式碼舉例說明了這個問題:
function addLinks() { for (var i=0, link; i<5; i++) { link = document.createElement("a"); link.innerHTML = "Link " + i; link.onclick = function () { alert(i); }; document.body.appendChild(link); } }
此程式碼旨在生成 5 個鏈接,每個鏈接在單擊時顯示自己的索引。但是,點擊後,所有連結都將顯示「連結 5」。這種異常源自於 JavaScript 中的閉包機制。
在第一個片段中,循環事件處理程序中定義的內部函數維護變數 i 的參考。但是,循環完成後,i 的值為 5。因此,當事件處理程序呼叫alert(i) 時,i 的值始終為 5,從而導致不正確的行為。
在第二個程式碼中透過將內部函數包含在立即呼叫的函數表達式(IIFE) 中可以解決此問題:
link.onclick = function (num) { return function () { alert(num); }; }(i);
IIFE 確保建立內部函數的新實例對於每次迭代,從而將i 的期望值保留在其範圍內。當事件處理程序執行時,它會使用從 IIFE 擷取的 i 值來警告正確的索引。
或者,更有效的方法是將i 的當前值直接分配給DOM 節點的屬性,在事件處理程序執行期間啟用輕鬆訪問:
link.i = i; link.onclick = function () { alert(this.i); };
此解決方案無需為每個連結建立新的函數物件。
以上是為什麼 JavaScript 迴圈在綁定事件處理程序時會產生意外行為?的詳細內容。更多資訊請關注PHP中文網其他相關文章!