理解闭包及其作用域

3

我有些难以理解闭包和作用域。我曾经相信自己已经理解了它们,但是我遇到了意想不到的行为。

function doSomething () {
    // Code unrelated to frag

    var rightDiv = document.createElement(rightDiv);

    var img, i, frag = document.createDocumentFragment();
    for (i = 0; i < photoIDs.length; i++){
        img = new Image();
        addClass(img, "popup-image-preview");
        img.src = "photos/"+photoIDs[i]+".jpg";
        frag.appendChild(img)
    }
    // add popup for preview
    addEvent(rightDiv, "mouseover", function() {
        showPopup(frag, this);
        console.dir(frag);
    });

    // more code unrelated to frag
}

我原以为onmouseover处理程序仍然可以访问包含图像的DocumentFragment。但是当我在控制台中查看时,它不再有任何子元素了。这个特定的匿名函数是否具有访问本次doSomething执行的局部变量值的能力,还是后续对doSomething的调用会影响先前执行的闭包?如果后者成立,则我的情况就可以理解,因为后续对frag的调用可能为空。


1
我相信闭包应该按预期工作。很奇怪。 - Delan Azabani
据我所知,你的假设是正确的,这一定有不同的原因或者你遇到了某些特殊情况... - Tim Büthe
我在想这是不是因为你重新调用了 doSomething 并重新绑定了事件?不确定这是否会丢弃旧的事件绑定(不太了解浏览器中的 JS)。 - Merlyn Morgan-Graham
这对我有效:http://jsfiddle.net/WxQDk/2/. - pimvdb
啊..所以如果我移除showPopup(..)的调用,控制台会按预期输出。这显然是我的错。showPopup将文档片段附加到一个div上。我假设当这发生时,DocumentFragment对象会被清空子元素? - rewolf
2个回答

0

一般来说,你是对的,你的代码应该按照你的期望工作。但有几个问题让我感到困惑:

  • rightDiv 在哪里定义的?看起来你正在给那个“节点”添加越来越多的mouseover事件,因为它不是上下文的一部分。

  • addEvent 或者 showPopup 是否会修改frag变量的任何内容?


抱歉..是的。我现在进行了编辑,解释它对每个执行都是唯一的。 - rewolf
@rewolf:能否请您展示代码,它是在哪里声明的以及它是如何定义的呢? - jAndy
我添加了它的定义行。doSomething 基本上是创建一个包含信息和另一个名为 rightDiv 的 div,它允许您在弹出窗口中查看图像。但是有许多这些 div,每个都由 doSomething 创建,其中一些没有弹出窗口。 - rewolf
谢谢。是showPopup的问题。我没有意识到将DocumentFragment附加到节点会清空DocumentFragment中的子元素。现在我正在使用cloneNode。 - rewolf

0

看起来闭包的工作效果符合预期。我的错误在于showPopup函数中,我将frag附加到文档节点上。我不知道这会导致DocumentFragment被清空。现在我在showPopup中使用node.appendChild(frag.cloneNode(true))

感谢大家的帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接