首頁 > web前端 > js教程 > 為什麼 Javascript 迴圈會導致事件處理程序出現意外行為?

為什麼 Javascript 迴圈會導致事件處理程序出現意外行為?

DDD
發布: 2024-12-22 06:26:38
原創
294 人瀏覽過

Why Do Javascript Loops Cause Unexpected Behavior in Event Handlers?

重訪 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 個鏈接,每個連結都有一個顯示當前連結 ID 的 onClick 事件。然而,當點擊這些連結時,它們都顯示「連結 5」。

這個問題的根本原因在於 Javascript 的函數級作用域。當迴圈完成時, i 變數保留值 5。這是因為 Javascript 函數在其詞法環境中是封閉的,這意味著它們可以存取周圍範圍中定義的變數。

此問題的解決方法是引入一個閉包,捕獲每次迭代的i 的當前值:

function addLinks () {
    for (var i=0, link; i<5; i++) {
        link = document.createElement("a");
        link.innerHTML = "Link " + i;
        link.onclick = function (num) {
            return function () {
                alert(num);
            };
        }(i);
        document.body.appendChild(link);
    }
}
登入後複製

在此程式碼中,為每個連結建立一個新的函數對象。它有自己的作用域和一個局部變數 num,它被賦予 i 的當前值。執行內部函數時,它引用閉包的 num 變量,該變量保留了循環中分配的正確值。

雖然這種方法很有效,但在建立新函數時會帶來效能損失對於每個事件偵聽器。更有效率的替代方案是使用 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);
    }
}
登入後複製

透過將 i 值直接儲存在 DOM 節點上,我們消除了對閉包的需要,從而提高了程式碼效率。

以上是為什麼 Javascript 迴圈會導致事件處理程序出現意外行為?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板