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

时间:2017-02-02 22:46:26

标签: javascript arrays for-loop addeventlistener

代码如下:

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],因为循环已经完成,但我该如何解决?该目标取决于相同的循环

1 个答案:

答案 0 :(得分:0)

for循环弄乱了Closure,因为它将相同的变量(k)传递给所有addClass次调用。因此,当调用addClass时,它会查找k的最新值(它将等于数组.length的长度,因此未定义索引)。发生这种情况是因为for的{​​{3}}在退出之前保持不变。因此,请使用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);
    });
  });
});