为何无法在addEventListener中使用变量i?猫图指针事件疑问
问题解析:为何点击事件回调中无法用
document.getElementsByClassName('cat')[i]替代[0] 场景回顾
你有两张类名为cat的图片,需求是点击第一张图片时,将它的pointer-events属性设为none,现有代码可实现功能,但疑惑为何回调里不能用[i]替代[0]。
核心原因:var的作用域与闭包陷阱
你用了var i来声明循环变量,var是函数级作用域,循环结束后,i的值会变成2(因为循环执行两次:i=0、i=1,最后i++到2时不满足i < elements.length(length是2),循环终止)。
当点击事件触发时,回调函数才会执行,此时它访问的i是循环结束后的全局(或函数级)变量,值为2。而document.getElementsByClassName('cat')返回的元素集合只有索引0和1的元素,[2]对应的是undefined,自然无法设置pointer-events属性。
优化写法推荐
写法1:用let替代var(块级作用域解决问题)
将循环变量的var改为let,let是块级作用域,每次循环都会创建一个独立的i变量,回调函数会捕获当前循环的i值:
let elements = document.querySelectorAll('.cat'); for (let i = 0; i < elements.length; i++) { if (i === 0) { elements[i].addEventListener('click', function(event) { console.log('Cursor switched'); document.getElementsByClassName('cat')[i].style.pointerEvents = 'none'; }); } }
写法2:直接引用当前点击的元素(最简洁可靠)
不需要依赖索引,直接用this或event.target获取被点击的元素,完全规避索引问题:
let elements = document.querySelectorAll('.cat'); // 直接给第一张元素绑定事件,无需循环 elements[0].addEventListener('click', function(event) { console.log('Cursor switched'); this.style.pointerEvents = 'none'; // 也可以用 event.target.style.pointerEvents = 'none'; });
写法3:用闭包保存索引值(兼容旧环境)
如果需要兼容不支持let的旧环境,可以用立即执行函数(IIFE)把当前的i值保存下来:
let elements = document.querySelectorAll('.cat'); for (var i = 0; i < elements.length; i++) { if (i === 0) { // 用闭包捕获当前循环的i值,命名为index (function(index) { elements[index].addEventListener('click', function(event) { console.log('Cursor switched'); document.getElementsByClassName('cat')[index].style.pointerEvents = 'none'; }); })(i); } }
内容的提问来源于stack exchange,提问作者catmau6
相关产品推荐
相关产品推荐

