JavaScript数组迭代绑定点击事件,如何获取正确索引?
解决数组迭代绑定点击事件时索引始终为数组长度的问题
这是典型的JavaScript闭包与作用域陷阱!你遇到的问题根源在于用var声明循环变量i——var的作用域是函数级的,不是块级的,所以整个循环里只有一个i的绑定。当点击事件触发时,循环早就执行完毕了,i已经被更新为数组的长度zoom.length,自然每次拿到的都是最后一个“无效”索引。
下面给你三种靠谱的解决办法,按推荐程度排序:
方法1:用let替代var(最简洁现代的方案)
let是ES6引入的块级作用域变量,每次循环都会创建一个全新的i绑定,点击事件的回调函数会捕获到当前循环迭代的那个i值,完美解决问题:
for (let i = 0; i < zoom.length; i++) { zoom[i].addEventListener('click', () => { openModal(i); }) } function openModal(index) { image.src = './img/screenshotSite' + index + '.png'; modal.style.display = 'block'; document.getElementsByTagName('*')[0].style.overflow = 'hidden'; }
方法2:用立即执行函数(IIFE)创建独立作用域(兼容旧环境)
如果需要兼容不支持ES6的旧浏览器,可以用立即执行函数把每次循环的i封装到独立作用域里,让回调函数捕获到正确的索引值:
for (var i = 0; i < zoom.length; i++) { // 用IIFE创建独立作用域,传入当前循环的i (function(currentIndex) { zoom[currentIndex].addEventListener('click', () => { openModal(currentIndex); }) })(i); } function openModal(index) { image.src = './img/screenshotSite' + index + '.png'; modal.style.display = 'block'; document.getElementsByTagName('*')[0].style.overflow = 'hidden'; }
方法3:给元素添加自定义属性(直观易懂的方案)
把索引直接存在每个图片元素的自定义属性里,点击时读取这个属性值,完全绕开作用域的问题:
for (var i = 0; i < zoom.length; i++) { // 把索引存入元素的data-index属性 zoom[i].dataset.index = i; zoom[i].addEventListener('click', function() { // 点击时读取当前元素的索引 const index = this.dataset.index; openModal(index); }) } function openModal(index) { image.src = './img/screenshotSite' + index + '.png'; modal.style.display = 'block'; document.getElementsByTagName('*')[0].style.overflow = 'hidden'; }
这三种方法都能解决你的问题,优先推荐第一种用let的方案,代码最简洁也符合现代JS的写法。
内容的提问来源于stack exchange,提问作者user14620717
相关产品推荐
相关产品推荐

