在循环中添加eventListener,并创建一个依赖于循环但在循环结束后仍然有效的侦听器函数



代码如下:

var classToAdd = 'myClass';
var addClass = function(el, cn) {
if (el.classList.contains(cn)) {
return;
} else {
el.classList.add(cn);
}
};
var bundles = [
{
selectedActivators: [`array containing 2 DOM objects`],
target: `DOM object`
},
{
selectedActivators: [`array containing 2 DOM objects`],
target: `DOM object`
},
{
selectedActivators: [`array containing 2 DOM objects`],
target: `DOM object`
}
];
for (var k=0; k<bundles.length; k++) {
for (var l=0; l<bundles[k].selectedActivators.length; l++) {
console.log(bundles[k].selectedActivators[l]); // log #1
console.log(bundles[k].target); // log #2
bundles[k].selectedActivators[l].addEventListener('mouseover', function() {
console.log(bundles[k]); // log #3
addClass(bundles[k].target, classToAdd);
});
bundles[k].selectedActivators[l].addEventListener('mouseout', function() {
removeClass(bundles[k].target, classToAdd);
});
} 
}

日志#1和#2完全按照预期工作,因此对象在进入事件侦听器之前是正常的,但日志#3打印:undefined

我知道当我转到页面并将鼠标悬停在eventListener目标上时,bundle[k]不再被定义,因为循环已经完成,但我该如何解决这个问题?该目标依赖于相同的循环

for循环正在扰乱Closure,因为它将相同的变量(k)传递给所有addClass调用。因此,当调用addClass时,它会查找k的最新值(它将等于数组.length的长度,因此未定义索引)。之所以会发生这种情况,是因为forScope在退出之前保持不变。因此,使用forEach,它用不同的作用域(回调的作用域)包围每个元素,从而解决您的问题。像这样:

bundles.forEach(function(bundlesK) {
bundlesK.selectedActivators.forEach(function(selActiv) {
selActiv.addEventListener('mouseover', function() {
addClass(bundlesK.target, classToAdd);
});
selActiv.addEventListener('mouseout', function() {
removeClass(bundlesK.target, classToAdd);
});
});
});

最新更新