理解闭包
JavaScript 中的闭包允许函数从直接外部访问变量范围,创建私有数据上下文。然而,即使封闭函数执行完毕,闭包引用的变量仍然可以访问。
循环中闭包的问题
考虑以下代码片段:
<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中文网其他相关文章!