一、引言
什么是“闭包”?它既是前端程序中常常会碰到的一个千年大坑,也是这个大坑唯一可以解决自身的办法。很多大牛对闭包都有自己的解释,但每个人的解释可能都不太一样,看太多反而混乱,这里,我会用一个小例子,尽量简单的说明这个“闭包”到底是什么,怎么识别?如何解决?
二、闭包
三、如何形成闭包
外层函数的作用域对象无法释放,导致:外层函数的局部变量被保存下来(可以重用)。
四、快速识别
五、例题说明
点击1,2,3按钮,获得对应按钮值,有如下代码:
<body>
    <h3>JS中的闭包陷阱</h3>
    <button>1</button>
    <button>2</button>
    <button>3</button>
    <script>
       var list = document.querySelectorAll(‘button‘);
       for(var i=0;i<list.length;i++){
           var b = list[i];
           b.onclick = function(){
               console.log(i);
           }
       };
    </script>
 </body>
打印结果:

坑:这属于典型的闭包问题,打不出0,1来,全部为3。
原因:变量i就1个,并且这段代码不仅是对外公开了一个变量i,还公开了三个不同的监听函数,分别绑定给不同的按钮。
如果看所有JS调用完成(函数外打印),i的值,如下:
console.log(‘JS调用完成,i=‘+i);
结果:

所以:此时所有JS都已调用完成,i的值等于3。但是,按钮的事件监听并没有调用,可它们都要用i,因此,这个时候,再手动调用事件监听,所获得的i值只能是3。
六、解决方法
闭包问题必须要靠闭包方案来解决
//方法一:把原本的一个闭包拆为三个
for(var i=0;i<list.length;i++){
    var b = list[i];
    b.onclick = outer(i);
}
function outer(num){
    function inner(){
       console.log(num);
    }
    return inner;
}
 //方法二:匿名函数变成有名函数
for(var i=0;i<list.length;i++){
     var b = list[i];
     b.onclick = (function(num){//外部函数--此处传递形参num,注意不能再取i为变量名,否则又会重复
        return function(){//内部函数
        console.log(num);
            }
     })(i);//闭包上下文变量i,实参
}
结果:

如果打印btn,实现代码和效果如下:
for(var i=0;i<list.length;i++){
     var b = list[i];
     b.onclick = (function(btn){//外部函数-
        return function(){//内部函数
        console.log(btn);
            }
     })(b);//传递b为实参
}

原文:http://www.cnblogs.com/ljq66/p/7668681.html