前言:在学习js的过程中遇到这么一个问题。
题目:点击页面上的钢琴键时,琴键变长
var piano = document.querySelectorAll('.piano');
for (var i = 0; i < piano.length; i++) {
piano[i].onclick = function () {
piano[i].classList.add('change')
setTimeout(() => {
piano[i].classList.remove('change')
}, 1000);
}
}
问题:以上代码刷新后,点击琴键时,没有反应,并报错。
Cannot read property ‘classList’ of undefined
当把var 改成 let 时 ,运行正常,琴键点击可以变长
for (let i = 0; i < piano.length; i++) {
piano[i].onclick = function () {
piano[i].classList.add('change')
setTimeout(() => {
piano[i].classList.remove("change")
}, 1000);
}
}
查询的一些解释:
- var定义的变量,可以预解析,提前调用的结果是undefined;
let定义的变量,不能预解析, 提前调用的结果是 报错。 - var定义的变量,变量名称可以重复,效果是重复赋值;
let定义的变量,变量名称不能重复,否则执行报错。 - var定义的变量作用域是全局/局部作用域。
let定义的变量如果在{}中只能在{}中调用。 - 在循环语句中var定义的循环变量和使用let定义的循环变量。执行原理和执行效果不同。
也可能是setTimeout是异步执行的造成的。
我的理解是当for(var…)时,页面打开就已经执行完成,在点击琴键就不在生效。
当for(let…)时,let将i绑定到for循环中,事实上它将其重新绑定到循环体的每一次迭代中。
setTimeout里面的function()属于一个新的域,通过var定义的变量是无法传入到这个函数执行域中的,通过使用let来声明块变量能作用于这个块,所以function就能使用i这个变量了。
原文链接:https://blog.csdn.net/weixin_44703582/article/details/124445632