疑惑:for循环绑定事件,事件内部引用循环里的变量,发现只会得到最后值,而不是循环到的每一个值。
回答:在javascript中,没有块级作用域,只有函数作用域,也就是说在执行一个函数的时候会新开辟内存空间,click方法必须要点击的时候才能会调用,但是for循环已经执行完毕,i等于最后一个值,所以当点击的时候总是最后一个。
云南之旅相册:
window.onload=function(){ //页面加载后再执行
var as=document.querySelectorAll("a"),
imgs=document.querySelectorAll("img");
for (var i = as.length - 1; i >= 0; i--) {//外循环
// console.log(i);//5 4 3 2 1 0
// console.log(this);//this指向window对象
as[i].onclick=function(){
// console.log(i);//点击之后打印-1,i是外部for循环完成之后的最终结果-1
for (var j = imgs.length - 1; j >= 0; j--) {
imgs[j].style.opacity='0';
// return;不能return,会影响停止后面的操作
// console.log(this);this指向当前被绑定事件的对象
// console.log(i);//点击之后打印一堆-1,i是外部for循环完成之后的最终结果-1
}
imgs[i].style.opacity='1';//报错,i不可用
}
}
};
解决方法1:利用call方法借用数组的indexOf方法,得到触发事件元素的index值
imgs[[].indexOf.call(as,this)].style.opacity='1';
//利用call方法借用数组的内置对象indexOf方法,将as替换原空数组,传入this查找并返回索引
解决方法2:保存外层函数的执行作用域,也就是用闭包来解决。
for (var i = as.length - 1; i >= 0; i--) {
(function(k) {
as[k].onclick=function(){
console.log(i);
for (var j = imgs.length - 1; j >= 0; j--) {
imgs[j].style.opacity='0';
}
imgs[k].style.opacity='1';
}
})(i);//以i为参数传给k函数自调用
}
//闭包的作用是把定义的变量保存到内存中,不被销毁,这里是就每次穿过来的i都被k接受并且保存。
闭包还有其他写法,如(funciton()()) !function()() ~function()() 等等
方法3:元素添加一个index属性保存你要用的值,然后直接从属性中取得。
for (var i = as.length - 1; i >= 0; i--) {
as[i].index=i;
as[i].onclick=function(){
for (var j = imgs.length - 1; j >= 0; j--) {
imgs[j].style.opacity='0';
}
imgs[this.index].style.opacity='1';
}
}
方法4:利用ES6中典型的let块级作用域。
for (let i = as.length - 1; i >= 0; i--) {
as[i].onclick=function(){
console.log(i);
for (var j = imgs.length - 1; j >= 0; j--) {
imgs[j].style.opacity='0';
}
imgs[k].style.opacity='1';
}
}
}//ES6中,for中的{}也属于块级作用域。
成了!