JavaScript事件回调中this可用而class1[i]为undefined的原因是什么?
问题原因说明
出现该现象是var关键字的作用域特性与闭包的延迟执行特性共同导致的,具体原理如下:
var声明的变量不存在块级作用域,你在for循环头部声明的var i本质是全局变量,整个循环过程中只会有这一个i变量,每次循环都会对同一个i进行赋值修改。当循环结束后,i的最终值为3(因为你的class1类数组长度是3,当i自增到3时不满足i < class1.length的条件,循环终止)。- 事件回调函数是异步触发的,只有当鼠标事件真正被触发时才会执行回调内的代码,此时for循环早已执行完毕,回调内读取的i就是全局的最终值3,而class1的有效下标为0、1、2,
class1[3]自然就是undefined。
而this可以正常指向触发元素,是因为DOM标准事件绑定的回调函数中,this默认会指向触发当前事件的DOM元素,和外部的i变量没有关联,所以不受上述问题影响。
常用修复方案
你可以选择以下任意一种方法解决该问题:
- 将循环变量的声明从
var i改为let i,let存在块级作用域,每次循环都会生成独立的、对应当前迭代的i变量,回调闭包会捕获对应循环的i值:
for (let i = 0; i < class1.length; i++) { // 原有回调代码保持不变即可 }
- 将类数组转为普通数组后用forEach遍历,每次迭代的item就是当前绑定事件的元素,不需要依赖下标访问:
Array.from(class1).forEach(item => { item.addEventListener('mouseover', function () { this.setAttribute("style", "background-color:cyan;color:#ffffff") }) item.addEventListener('mouseleave', function () { this.setAttribute("style", "background-color:#fff;color:#000") }) })
内容的提问来源于stack exchange,提问作者Akil
相关产品推荐
相关产品推荐

