JS中for循环输出同一变量值的问题

例一

var data = [];
for(var k = 0; k < 3; k++){
      data[k] = function(){
             return k;
       };

  } 
alert(data[0]());

预想中应输出0,但结果为3
首先必须清楚一下几点

  • . 在JS中没有块级作用域的概念,for循环中定义的var k实际上是一个window全局变量。
  • . 内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。即每个环境都可以向上搜索作用域链,以查询变量和函数;但任何环境不能向下搜索作用域链而进入另一环境。
  • .

在这段代码中,执行data[0]()时,调用函数return k赋值给data[k],在这个函数作用域中没有定义k,因此向上搜索找到了全局变量k。由于每次循环更改的都是同一个空间的k,当循环执行到K=3,由于看<3不成立循环里面的代码不执行,但是k所在空间的值已经为3,因此当调用data[0]()时,return K执行后所赋的值就是3.

解决这个问题的方式就是引入闭包

//加一层闭包,i以函数参数形式传递给内层立即执行函数 
 for(var k = 0; k < 3; k++){
     data[k] = (function(){
              return k;
      })(k);

 }  

还有下面的(此处引用一些网上的方法)

<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
<title>闭包演示</title> 
</head>  
    <body>  
        <p>1</p>  
        <p>2</p>  
        <p>3</p>  
        <p>4</p>  
        <p>5</p> 
        <script type="text/javascript">
            window.onload=function() {  
                 var ps = document.getElementsByTagName("p");  
                 for( var i=0; i<ps.length; i++ ) {  
                       ps[i].onclick = function() {  
                       alert(i);  
                     }  
                 }  
            }  
        </script> 
    </body>  
</html>

点击每个段落都弹出5,原因同上,都是用的同一个内存空间的i

提供一下解决方案

//sava1:加一层闭包,i以函数参数形式传递给内层函数 
 for( var i=0; i<ps.length; i++ ) {  
 (function(arg){   
  ps[i].onclick = function() {   
   alert(arg);  
  };  
 })(i);//调用时参数  
 } 
//save2:加一层闭包,i以局部变量形式传递给内存函数 
 for( var i=0; i<ps.length; i++ ) {  
 (function () {  
  var temp = i;//调用时局部变量  
  ps[i].onclick = function() {  
  alert(temp);  
  }  
 })();  
 }
//save3:加一层闭包,返回一个函数作为响应事件(注意与3的细微区别) 
 for( var i=0; i<ps.length; i++ ) {  
 ps[i].onclick = function(arg) {  
  return function() {//返回一个函数  
  alert(arg);  
  }  
 }(i);  
 } 
//save4:将变量 i 保存给在每个段落对象(p)上  
 for( var i=0; i<ps.length; i++ ) {  
  ps[i].i = i;  
  ps[i].onclick = function() {  
  alert(this.i);  
  }  
 }
//save5:将变量 i 保存在匿名函数自身  
 for( var i=0; i<ps.length; i++ ) {  
 (ps[i].onclick = function() {  
  alert(arguments.callee.i);  
 }).i = i;  
 }   
} 
//save6:用Function实现,实际上每产生一个函数实例就会产生一个闭包
 for( var i=0; i<ps.length; i++ ) {  
  ps[i].onclick = new Function("alert(" + i + ");");//new一次就产生一个函数实例 
 } 
//save7:用Function实现,注意与6的区别  
 for( var i=0; i<ps.length; i++ ) {  
   ps[i].onclick = Function('alert('+i+')'); 
 }
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值