JavaScript闭包用于jQuery事件处理程序

3

我有一个对象列表,每个对象都有一个.bullet属性,它是一个SPAN标签。我想使用jQuery将单击事件绑定到SPAN标签上,并使用处理程序对SPAN标签执行某些操作。我看到了一些我不理解的行为,所以希望有人能解释一下发生了什么。基本上,这个第一个代码示例可以工作:

for (var i = 0 ; i< length ; i++) {

            (function(){
                dataNode = dataNodeList[i];

                var handler = function(e) {

                    e.data.node.bullet.firstChild.nodeValue = "- ";


                };


                $(dataNode.bullet).on("click",{node:dataNode},handler);


            })();

        }

然而,第二种变化不起作用:
for (var i = 0 ; i< length ; i++) {

            (function(){
                dataNode = dataNodeList[i];

                var handler = function() {

                    dataNode.bullet.firstChild.nodeValue = "- ";


                };


                $(dataNode.bullet).on("click",handler);


            })();

        }

在这个第二个例子中,
dataNode.bullet.firstChild.nodeValue = "- ";

对我预期的SPAN值没有影响。由于JavaScript闭包,我希望dataNode.bullet仍然指向我想要更改的SPAN。那么,有人可以解释为什么会失败吗?谢谢。


两件事情:在该函数中使用 var 声明 "dataNode",并将 "i" 传递给循环中的立即调用函数。当然,也要将 "i" 添加到其参数列表中。 - Pointy
可能是在for循环中分配点击处理程序的重复问题 - 这是一个非常普遍的问题,因为所涉及的行为性质并不明显。 - Pointy
啊,谢谢你指出我忘记在循环内声明变量了。 - user1052335
1个回答

6

试试这个:

for (var i = 0 ; i< length ; i++) {
    (function(index){
        var dataNode = dataNodeList[index];

        var handler = function() {
            dataNode.bullet.firstChild.nodeValue = "- ";
        };

        $(dataNode.bullet).on("click",handler);
    })(i);
}

闭包定义了一个新的范围。这是必要的,因为你的处理程序直到循环结束后才会被调用,所以在调用时i不是作用域的一部分,或者(在某些情况下)具有循环的最后可能值。


这似乎解决了主要问题。现在,至少dataNode.bullet似乎指向了正确的span元素。谢谢。不过我看到另一个问题。dataNode.bullet.firstChild.nodeValue =“-”神秘地删除了span的内容。但是,如果我紧接着加一行样式来设置span,那么两个更改都会出现。我不确定这是否与原始问题有关。 - user1052335
你能解释一下为什么在匿名函数中需要放置索引参数吗?我从概念上不理解它会有什么区别,而且在不使用索引参数的情况下,我的代码也能正常工作,只是声明dataNode的位置有所不同。 - user1052335
@AdamCarter 在这种情况下将索引作为参数提供给闭包可能并不是严格必要的,但它确实有助于使代码更清晰。 - Shmiddty
@Shmiddty 我很确定索引参数是必需的。请看http://jsfiddle.net/v4sSD/和http://jsfiddle.net/vfwnU/之间的区别。 - Rag

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