一、引言
什么是“闭包”?它既是前端程序中常常会碰到的一个千年大坑,也是这个大坑唯一可以解决自身的办法。很多大牛对闭包都有自己的解释,但每个人的解释可能都不太一样,看太多反而混乱,这里,我会用一个小例子,尽量简单的说明这个“闭包”到底是什么,怎么识别?如何解决?
二、闭包
三、如何形成闭包
外层函数的作用域对象无法释放,导致:外层函数的局部变量被保存下来(可以重用)。
四、快速识别
五、例题说明
点击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