下面的代码中,为什么elems[i]得到的结果是:undefined?
代码及运行效果也可在JS Bin中查看:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS Bin</title>
</head>
<body>
<div class="link">
<a href="#">壹</a>
<a href="#">贰</a>
<a href="#">叁</a>
<a href="#">肆</a>
</div>
</body>
</html>
var elems = document.getElementsByTagName("a");
for(var i = 0; i < elems.length; i++ ){
elems[i].addEventListener("click",function(){
console.log("i = " + i);
//运行结果:"I am link # undefined",为什么得到的elems[i]是undefined呢?
console.log("I am link # " + elems[i]);
});
}
首先
for语句中使用var声明变量是的作用域问题,在MDN中是这样描述的:该表达式可以使用var或let关键字声明新的变量,使用var声明的变量不是该循环的局部变量,而是与for循环处在同样的作用域中。用let声明的变量是语句的局部变量
因此你使用var i=0;是相当于声明了一个跟for语句同级的变量i;等价的写法类似:
然后
理解了上面的话,下面理解值为undefined就不难了,此时我们再看循环:我们在DOM中有四个元素,因此elems.length的值为4;由于for循环值是我们对每个DOM绑定了一个点击函数,函数的触发执行的时机肯定是晚于for选执行的时间的。因此,每个点击事件最终拿到的i都是for循环满足条件后的i(注意 i++ ),也就是4;这时需要注意数组访问是以0开始的,因此DOM元素的每个下标是 0 1 2 3 这时你去访问elems[4]就是在访问一个数组中不存在的值,肯定是undefined
解决办法可以采用let ;let具有块级作用域可以解决上面的问题,或者使用自执行函数闭包解决;
更详细的内容可以看:https://segmentfault.com/a/11...