for循环内使用addEventListener仅对最后一个元素生效该如何解决?
问题原因
你遇到的是经典的循环内异步回调闭包变量共享问题:
- 用
var声明的迭代变量o不存在块级作用域,会被提升到全局作用域,整个循环全程只会共用同一个o变量 - 事件回调是异步触发的,等到回调执行时,循环早已执行完毕,此时
o的值已经固定为数组最后一个元素的索引,所以所有回调读取的inputIds[o]都是最后一个ID
解决方法
方案1:改用let声明迭代变量(最简单,ES6+环境推荐)
把循环里的var o改成let o,let具备块级作用域,每次循环都会生成一个独立的o变量绑定到当前迭代上下文,回调会捕获对应迭代的o值:
//Add event listener for (let o in inputIds) { document.getElementById(inputIds[o]).addEventListener('ionBlur', function () { validateTime(inputIds[o]); }, false); document.getElementById(inputIds[o]).addEventListener('ionChange', function () { filterChar(inputIds[o]); }, false); }
方案2:用forEach遍历数组(语义清晰,兼容性好)
直接遍历ID数组,每次迭代的参数都是独立的作用域变量,不需要手动处理作用域:
//Add event listener inputIds.forEach(function(id) { const inputEl = document.getElementById(id); inputEl.addEventListener('ionBlur', function () { validateTime(id); }, false); inputEl.addEventListener('ionChange', function () { filterChar(id); }, false); });
方案3:用立即执行函数(IIFE)缓存变量(兼容ES5及更早老旧环境)
如果需要兼容不支持ES6的环境,可以用IIFE给每次循环的ID创建独立闭包缓存:
//Add event listener for (var o in inputIds) { (function(currentId) { document.getElementById(currentId).addEventListener('ionBlur', function () { validateTime(currentId); }, false); document.getElementById(currentId).addEventListener('ionChange', function () { filterChar(currentId); }, false); })(inputIds[o]); }
内容的提问来源于stack exchange,提问作者pilotman
相关产品推荐
相关产品推荐

