理解閉包
Java 中的閉包允許函數從直接外部存取變數範圍,建立私有資料上下文。然而,即使封閉函數執行完畢,閉包引用的變數仍然可以存取。
循環中閉包的問題
考慮以下程式碼片段:
<code class="javascript">for (var i = 0; i < 5; i++) { link = document.createElement("a"); link.innerHTML = "Link " + i; link.onclick = function (num) { return function () { alert(num); }; }(i); document.body.appendChild(link); }</code>
在此範例中,作為num 傳遞給內部函數的i 值由在所有連結元素之間建立「共享變數」的閉包捕獲。這表示單擊任何連結將始終顯示 i 的最後一個值(在本例中為 4)。
使用IIFE(立即呼叫函數表達式)作為函數工廠
要解決此問題,請為每個連結建立IIFE,並將i 的值作為參數傳遞:
<code class="javascript">function addLinks() { for (var i = 0; i < 5; i++) { link = document.createElement("a"); link.innerHTML = "Link " + i; // IIFE used as a function factory link.onclick = (function (num) { return function () { alert(num); }; })(i); document.body.appendChild(link); } }</code>
在此版本中,每個IIFE 建立一個隔離範圍,其中i 的值被凍結在函數建立的時間。這確保每個連結元素都有自己的 i 私有副本,無論點擊的順序為何。
替代方法:函數產生器
另一個選項是使用函數產生器建立引用i 目前值的函數:
<code class="javascript">function generateMyHandler(x) { return function () { alert(x); }; } for (var i = 0; i < 5; i++) { link = document.createElement("a"); link.innerHTML = "Link " + i; link.onclick = generateMyHandler(i); document.body.appendChild(link); }</code>
在在這種情況下,generateMyHandler 函數傳回一個新函數,該函數在呼叫時已綁定到i 的特定值函數呼叫。
透過了解 JavaScript 閉包如何捕捉變數並使用適當的技術建立隔離作用域,開發人員可以有效處理涉及共享變數的複雜循環場景。
以上是為什麼循環中的閉包會使所有連結顯示相同的值?的詳細內容。更多資訊請關注PHP中文網其他相關文章!