这是因为在js中没有块级作用域的概念,在js中仅有全局作用域和函数作用域,也就是说你在for中声明的变量i,相当于这样:window.onload = function () { var i; }好了,上面这个理解后,你试试这段代码:window.onload = function () { var arr = document.getElementsByTagName("div"); for (var i = 0; i < arr.length; i++) { arr[i].onclick = function () { console.log(i); }; } console.log('i=',i); } 你会发现console.log这句输出5。好,再往上说,onclick中保存的是一个匿名函数在内存中的位置,也叫指针。 当你单击的时候,因为onclick中是一个函数指针,所以会去执行,这个时候,你的代码让它去读变量i的值,这时变量i 的值就是真真的5
var i;
}好了,上面这个理解后,你试试这段代码:window.onload = function () {
var arr = document.getElementsByTagName("div"); for (var i = 0; i < arr.length; i++) {
arr[i].onclick = function () {
console.log(i);
};
}
console.log('i=',i);
}
你会发现console.log这句输出5。好,再往上说,onclick中保存的是一个匿名函数在内存中的位置,也叫指针。
当你单击的时候,因为onclick中是一个函数指针,所以会去执行,这个时候,你的代码让它去读变量i的值,这时变量i 的值就是真真的5
很显然,这里的变量i的赋值循环跟事件触发不是同步执行的,事件触发机制是侦听然后触发,所以上面的代码执行完之后,5个div元素侦听其自身的onclick事件,等待鼠标的触发,不触发函数体是不会被执行,而触发之后函数体内的代码执行,此时i就显而易见,不是每个索引值,而是经过循环之后的最终值。自己在写一些事件的时候,有时也会不经意的犯这个错误,避免的思考原则就是把事件执行函数和顺序代码函数分开来看,不要混淆在一起。解决方法:
直接的解决方法至少目前没有研究过,除非用jquery的object.each(function(i){......}); 上面的i可以按你的需求直接使用,不会受到顺序代码执行后的影响,具体可以去看下jquery的each方法不过如果不套用jquery框架,最能想到的方法就是扩展元素的自定义属性,可以安排div元素的一个自定义属性
<div nowIndex="1">...</div>
<div nowIndex="2">...</div>
<div nowIndex="3">...</div>
....
通过在事件函数中获得该属性后实现。为啥说不是直接解决,自定义属性显而易见不是直接方法,而jquery则要套用该框架所以也不是直接解决。按变量存放原则应该是有书写代码的方法,这里只能抱歉,暂时没有更多时间研究了。
window.onload = function () { var arr = document.getElementsByTagName("div"); for (var i = 0; i < arr.length; i++) {
arr[i].onclick = (function (i) { return (function () { console.log(i); }) })(i);
} }
<script type="text/javascript">
onload = function(){
var div=document.getElementsByTagName("div");
for(var i= 0;i<div.length;i++){
div[i].addEventListener('click', (function(i){return function() {alert(i);};})(i),false);
}
alert(i);
};
</script>