通过闭包解决 JavaScript 臭名昭著的循环问题
考虑以下代码,旨在生成五个具有唯一警报事件的链接以显示其各自的 ID:
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:
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); } }
理解闭包魔法
此代码成功的关键在于闭包的概念。在 JavaScript 中,闭包是一个保留对创建它的函数的词法环境的访问的函数。换句话说,它可以访问外部函数中定义的变量和参数,而不管其自身的作用域如何。
在第一个代码片段中,内部函数引用了变量 i,该变量被提升到了函数的范围。当循环迭代时,变量 i 会更新,并且内部函数始终引用其最新值。这会导致所有链接在单击时显示“链接 5”。
在第二个代码片段中,外部函数文字创建一个新函数对象,该对象具有自己的作用域和局部变量 num,其值设置为当前值i 的值。函数对象作为链接 onclick 事件的事件处理程序返回。
至关重要的是,内部函数是在外部函数的词法环境的上下文中创建的,其中包括变量 num。因此,内部函数继续访问 num 并返回一个函数,该函数在单击链接时提醒正确的 ID。
这种方法确保每个链接都有自己唯一的闭包,从而保留 i 的正确值即使循环终止后也是如此。
以上是为什么使用闭包可以解决 JavaScript 的循环和闭包问题?的详细内容。更多信息请关注PHP中文网其他相关文章!