<body>
     <div style="border: 1px solid red;">1</div>
     <div style="border: 1px solid red;">2</div>
     <div style="border: 1px solid red;">3</div>
     <div style="border: 1px solid red;">4</div>
     <div style="border: 1px solid red;">5</div>
     <div style="border: 1px solid red;">6</div>
     <div style="border: 1px solid red;">7</div>
 </body>
var divArr = document.getElementsByTagName('DIV');
for(var i=0;i<divArr.length;i++){
    divArr[i].onclick = function(){alert(i);};
}为什么alert(i)总是同一个值,求原理说明,求解决方案?

解决方案 »

  1.   

    for (var i=0; i<divArr.length; i++){
      (function(){
         var j=i;
         divArr[j].onclick = function(){alert(j);};
      })();
    }这样写吧
      

  2.   


    请问为什么这样就可以了:
    var divArr = document.getElementsByTagName('DIV');
    for(var i=0;i<divArr.length;i++){
        (new Function('divArr['+i+'].onclick = function(){alert('+i+');};'))();
    }
    求说明原理?
      

  3.   

    原理就是js中的事件是异步的,也就是在触发那一刻才会执行事件监听函数(也就是onclic很函数)。
    如楼主的写法,当onclick事件触发时,也就是当它执行的时候,for循环早就执行完了,这时候,i=divArr.length,那么楼主alert(i)的时候,总是会得到divArr.length的值。。而当我们
      (function(){
      var j=i;
      divArr[j].onclick = function(){alert(j);};
      })();
    这样写的时候,我们定义了一个闭包,把i传递进去,并执行这个闭包(它的执行是同步的)。这时候,onclick绑定的是传递进去的i值,而不是循环结束的i值。。因此,就能得到正确的结果
      

  4.   

      (function(i){
      divArr[i].onclick = function(){alert(j);};
      })(i);
    补充一下,这样写更符合我给你解释的原因
      

  5.   

    楼主那种做法声明的变量i是位于全局作用域,而当Javascript解释器执行该函数时,就直接到全局作用域中
    访问变量i。而变量i随着循环,变量i的值就变成了7。所以alert(i)就总是同一个值7!至于二楼的那种做法则是在函数中声明了各自自己的变量j并且保存了自己的值,所以当Javascript解释器执行该函数时,就会到自己的函数中找自己定义的变量j的值。所以当然就正确啦!这事实上是个作用域链的问题。定义的每个函数都是个局部作用域。
      

  6.   


    请问为什么这样就可以了:
    var divArr = document.getElementsByTagName('DIV');
    for(var i=0;i<divArr.length;i++){
      (new Function('divArr['+i+'].onclick = function(){alert('+i+');};'))();
    }
    求说明原理?
      

  7.   

    查阅 js闭包 这个主题简单说你使用的i这个变量  存在于这个内部区域中 
    你的onclick事件到执行的时候 才访问 i这个变量
    想想看 这个时候 i都已经=divArr.length 了
      

  8.   

    使用Function构造函数来创建函数,Function构造函数要求传递的参数是字符串类型。所以,如果传给Function构造函数的参数不是字符串类型,Javascript会先把这些参数都转换成字符串,然后再执行Function构造函数。如上面的代码循环第一次执行时代码会是这样:
    (new Function('divArr['+0+'].onclick = function(){alert('+0+');};'))(); //因Function构造函数要求传递的是字符串类型
    所以,当运行代码时,其各自有各自i的值。不过,这种方式效率比较低。特别是用在循环中。因为每次循环都会创建一个函数对象。而使用函数直接量function(){};只会创建一个函数对象(即使是用在循环中)。