javascript - 修复循环中的闭包

标签 javascript closures

我正在阅读 David Flanagan 的 JavaScript:权威指南,我被困在以下示例中:

window.onload = function() {
    var elements = document.getElementsByClassName("reveal");
    for(var i = 0; i < elements.length; i++) {
        var elt = elements[i];
        var title = elt.getElementsByClassName("handle")[0];
        title.onclick = function() {
            if(elt.className == "reveal") elt.className = "revealed";
            else if(elt.className == "revealed") elt.className = "reveal;"
        }
    }
};

<div class="reveal">
    <h1 class="handle">Click Here to Reveal Hidden Text</h1>
    <p>This paragraph is hidden. It appears when you click on the title.</p>
</div>

问题是当前形式的代码可以工作,但是如果我要添加多个 divreveal,无论 h1 元素我点击,只有最后一个会展开。我应该在代码中更改什么才能使其在单独的 div 上工作?

附言我确实知道由于问题的性质是循环内的闭包,所以经常会问这种问题,但是鉴于 SO 上类似问题的解决方案,我无法使我的代码正常工作。谢谢。

最佳答案

在 JavaScript 中,变量作用域是在函数级别设置的。函数创建闭包,它本质上定义了作用域的边界。 子作用域 可以访问定义在父作用域 中的变量,反之则不行。

当您调用 onclick处理函数,它必须在作用域链向上查找变量elt。因为elt未在当前范围内声明。

范围链中的下一级是您的 window.onload处理函数(即闭包)。在此范围内,变量 elt 声明的,它的值由循环设置。 但请记住,当您单击 <h1>并调用 onclick处理程序,循环已经终止。因此,elt将始终是循环中设置的最后一个值。这就是为什么你总是得到 elt作为最后一个元素。

要解决此问题,您可以使用立即执行函数。立即执行函数创建一个新的闭包(和作用域),其中 elt在本地声明。因为变量 elt现在在这个新的内部作用域中声明,它不会被父作用域中的循环修改:

window.onload = function() {
    var elements = document.getElementsByClassName("reveal");
    for(var i = 0; i < elements.length; i++) {
        var elt = elements[i];
        var title = elt.getElementsByClassName("handle")[0];
        title.onclick = (function(elt) {
            return function() {
                if(elt.className == "reveal") elt.className = "revealed";
                else if(elt.className == "revealed") elt.className = "reveal;"
            };
        })(elt);
    }
};

关于javascript - 修复循环中的闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30990291/

相关文章:

javascript 大整数舍入因为精度? (为什么?)

javascript - 删除并破坏 angularjs 中特定位置的 json 数据

javascript - 如何发送带有链接的 $POST ?用java或任何合适的东西?

javascript - 如何阅读 Javascript 闭包语法?

javascript - 操纵闭包中定义的变量

c# - 在使用闭包的 LINQ 语句中,是否可以在闭包中指定 where 子句?

javascript - 在angularjs中声明多个服务依赖

javascript - HTML5 文件系统 : file not created on device

ios - iOS中 block (Objective-C)和闭包(Swift)之间的区别

javascript - 闭包中变量未定义?