来源: 吾推网  发布时间: 2018-03-22   次浏览
现在页面上有3个按钮
我们循环给按钮加点击事件
然后想点哪个按钮就弹当前按钮所在的序号
发现每次都是弹出最后一个按钮的序号
这是什么原因呢?
接下来就让我们通过例子来理解下这个问题

function test(){
    var oBtn=document.getElementsByTagName('button');
    for(var i=0;i<oBtn.length;i++){
       oBtn[i].onclick=bclick;
       function bclick(){
          console.log(i);
          var i=999;
       }
    }
}
test();//点击输出的是10
//为什么呢?因为for循环是没有作用域的,当前作用域在test函数上,变量i会提升到test函数的作用域上;
//当点击按钮时,会执行函数bclick,输出i,此时该函数内没有定义i
//此时会向函数外层找,在test函数的作用域上找到了i,而此时的i已经是2了;
function test(){
    var oBtn=document.getElementsByTagName('button');
    for(var i=0;i<oBtn.length;i++){
       oBtn[i].onclick=bclick;
       function bclick(){
          console.log(i);
          var i=999;
       }
    }
}
test();//点击输出的是undefined
//为什么此时输出undefined?;
//因为点击按钮,执行函数bclick,js预解析时,发现bclick内有定义i,但是在输出时,i还没被赋值,于是会输出undefined
//如果var i=999;放输出前,则会输出999
function test(){
    var oBtn=document.getElementsByTagName('button');
    for(var i=0;i<oBtn.length;i++){
       oBtn[i].onclick=bclick;
       function bclick(){
          console.log(i);
       }
       bclick();
    }
    var i=88;
    console.log(i);
}
test();
//输出的是0、1、2 88
//点击输出88
//for循环内调用函数bclick分别执行并输出了0,1,2,注意for循环中的i是在test函数作用域上
//循环结束,此时i已经是2了,然后继续往下走,i又被重新定义并赋值了88
//此时再点击按钮,输出的就是test作用域中的i,也就是最后被赋值了88的i
//解决按钮点击,分别弹出不同数值的方法
//下面来介绍3种
//方法1:
function test(){
    var oBtn=document.getElementsByTagName('button');
    for(let i=0;i<oBtn.length;i++){
       oBtn[i].onclick=bclick;
       function bclick(){
          console.log(i);
       }
    }
}
test();
//通过let把i的作用域控制在循环体内
//let在for循环中有一个特点
//就是在循环语句之中是父作用域,
//在循环体中是子作用域
//方法2:
function test(){
    var oBtn=document.getElementsByTagName('button');
    for(let i=0;i<oBtn.length;i++){
       oBtn[i].index=i; 
       oBtn[i].onclick=bclick;
       function bclick(){
          console.log(oBtn[i].index);
       }
    }
}
test();
//把i记录到按钮的自定义属性上
//方法3:
function test(){
    var oBtn=document.getElementsByTagName('button');
    for(var i=0;i<oBtn.length;i++){
        (function(i){
            oBtn[i].onclick=bclick;
            function bclick(){
              console.log(i);
            }
        })(i);
    }
}
test();
//通过闭包的方式