<script>
var imgs = document.getElementsByTagName('img');
for (var i = 0, len = imgs.length; i < len; i++) {
imgs[i].index = i;
imgs[i].onmouseover = function(){
// console.log(i);
console.log(this.index);
}
}
</script>
假如HTML页面有8个IMG标签的话,我的理解是脚本先执行循环不是吗?循环次数也只有8次, 但是 为什么实际的执行结果却是 只要触发循环内的事件 就可以一直执行触发事件既定的语句并且能够准确的找到所触发标签的下标呢。这段代码到底是怎么个执行逻辑呢?
获取到名字为img的标签
len = imgs的长度,如果i<len 等话执行循环
把i赋值给imgs下标为i的位置
并设置一个鼠标移出事件在console打印这个下表
你获取的是img标签的长度当然会一直执行咯,
这个设计到闭包的问题,你直接打印i,得到的只是i最后循环到的最大值8。this.index是imgs[i].index = i; 这里赋值的img的property,index这个property记录当前的i(因为i不是对象,不是地址引用,所以里面打印this.index为当前的for到的i值),你要打印i要做个闭包,将生产的处理函数引用到当前循环到的i值就行
var imgs = document.getElementsByTagName('img');//获取所有图片
for (var i = 0, len = imgs.length; i < len; i++) {
//一定要先将i的值作为imgs的一个属性保存起来,注意
imgs[i].index = i;
imgs[i].onmouseover = (function (i) {
return function () {
console.log(i);//这里和传入到匿名函数的参数值形成闭包指向当前的i循环值
// console.log(this.index);
}
})(i)//传入当前执行到的i值
}
首先浏览器在解析的时候,会先给每个img都循环上去一个onmouseover的事件,之所以每次移动上去都可以触发是因为每个img上面都有绑定的onmouseover事件,而且不管移动上去多少次都会触发,这个是触发它绑定的事件,与之前的循环8次没有关系,能够准确的找到所触发标签的下标是因为index是img[i]的一个自定义属性,它不会随着循环的结束直接跳转到8, console.log(this.index)其中this代表的是触发onmouseover事件的那个img,
你可以先弹出一下你的imgs.length的长度与你目标中的一致不一致,然后在执行你的for循环
第一你要理解闭包和作用域的概念:你再循环中将本次循环的次数赋值给了一个变量。你问为什么可以准确的找到触发函数的标签. 、
其实 当你在循环中将次数赋值给变量后,这个变量相对于外界是封闭的,它的作用域就是只在这个for 循环中有效(这就是闭包的概念。
在java 中称为对象作用域,) 只要你在作用域中不再次改变他的值,他的值就是固定的了。
还有你的这段代码 var imgs = document.getElementsByTagName('img');//获取所有图片
len = imgs.length;
for (var i = 0,i < len; i++) {
imgs[i].index = i;
imgs[i].onmouseover = (function (i) {
return function () {
console.log(i);
// console.log(this.index);
}
})(i)
写法不规范,你应该将长度变量先定义好再给下面使用。这样就不会循环一次就拿一次数组的长度属性,提高效率。(虽然在小数据下看不出差别但是为了以后,兄弟你要多注意些)