我试图为ready回调中元素的所有子div设置onmouseenter函数。所以身体的负荷是
function ready(){
for(var i=0;i<document.getElementById("pieces").childNodes.length;i++){
var n=document.getElementById("pieces").childNodes.item(i);
n.onmouseenter=function(){showBorder(n);};
n.onmouseleave=hideBorder;
}
}
但是所有获取其onmouseenter函数的div都使用了在循环结束时出现的n值。我希望每个onmouseenter在设置回调时使用n的值。
我该怎么办? 提前致谢
答案 0 :(得分:1)
问题是处理程序绑定到同一个n
。因此,更改n
会更改所有处理程序的n
。
您可以通过将n
传递给每次迭代执行的立即函数来“本地化”n
。这使得每个处理程序的n
绑定到立即函数的n
,而不是函数n
的{{1}}
ready
答案 1 :(得分:0)
JavaScript具有函数级范围,因此在{{1}中声明变量n
(但不 document.getElementById('pieces').childNodes.item(i)
到n
的赋值) }} loop实际上被提升到for
函数的顶部。
要理解这一点,假设您的代码实际上是这样编写的,因为这是JavaScript引擎实际解释它的方式:
ready
function ready() {
var i, n;
for (i = 0; i < document.getElementById('pieces').childNodes.length; i++) {
n = document.getElementById("pieces").childNodes.item(i);
n.onmouseenter = function () { showBorder(n); };
n.onmouseleave = hideBorder;
}
}
到function () { showBorder(n); }
的{{1}}属性的赋值创建了一个闭包,当该匿名函数实际执行时,它将访问范围内的任何和所有数据。创建的时间,即调用n
函数的时间。因此,这些onmouseenter
方法中的每一个都将引用变量ready
,该变量在onmouseenter
执行完成时具有等于n
的值
我建议使用以下代码段:
ready
document.getElementById('pieces').childNodes.length
一次并将该内存位置分配给function ready() {
var pieces, i, l, n;
pieces = document.getElementById('pieces').childNodes;
for (i = 0, l = pieces.length; i < l; i++) {
n = pieces.item(i);
n.addEventListener('mouseover', (function (m) {
showBorder(m);
})(n), false);
n.addEventListener('mouseout', hideBorder, false);
}
}
变量,以避免每次需要引用该组节点时进行另一次查找。document.getElementById('pieces').childNodes
循环中的比较语句在每次迭代时执行,因此不是查找pieces
,而是重复将其分配给变量for
一次并引用每次都是变量。pieces.length
方法是分配事件处理程序的最糟糕方式,因为你只能在任何地方注册给定DOM元素的单个函数时间。 l
方法是分配处理程序的首选方法,除非您希望用户使用旧版本的Internet Explorer,而不是on<event>
方法。addEventListener
和attachEvent
事件不是标准DOM事件,而是Microsoft为旧版Internet Explorer添加的自定义事件。它们被添加到DOM Level 3规范中,Firefox和Opera引入了对这些事件的支持,但Webkit仍然不支持它们。