當嘗試使用循環將事件處理程序附加到動態生成的元素時,就會出現臭名昭著的JavaScript 循環問題。在以下程式碼片段中:
function addLinks() { for (var i = 0, link; i < 5; i++) { link = document.createElement("a"); link.innerHTML = "Link " + i; link.onclick = function () { alert(i); // WRONG: i will always be 5 }; document.body.appendChild(link); } }
點擊任何產生的連結時,警報始終顯示「連結 5」。這是因為用 var 定義的 JavaScript 變數是函數作用域的,而不是區塊作用域的。當迴圈結束時,i 保持值 5,所有內部函數都會引用它,從而得到統一的輸出。
修正的解決方案在於捕捉閉包內 i 的值。考慮這個片段:
function addLinks() { for (var i = 0, link; i < 5; i++) { link = document.createElement("a"); link.innerHTML = "Link " + i; link.onclick = function (num) { // Closure around i return function () { alert(num); // num retains its original value }; }(i); // Execute the outer function immediately to capture i document.body.appendChild(link); } }
在這種情況下,num 綁定到每次迭代的 i 的當前值。執行內部函數時,num 總是設定為循環執行時 i 的值。
此外,存在一種利用DOM 節點儲存資料的有效替代方案:
function linkListener() { alert(this.i); } function addLinks() { for (var i = 0; i < 5; ++i) { var link = document.createElement('a'); link.appendChild(document.createTextNode('Link ' + i)); link.i = i; link.onclick = linkListener; document.body.appendChild(link); } }
透過將資訊附加到DOM 元素本身,避免了對額外函數物件的需求,從而提高了效率。
以上是為什麼我的 JavaScript 迴圈在附加事件處理程序時總是輸出計數器變數的最終值?的詳細內容。更多資訊請關注PHP中文網其他相關文章!