闭包是一个比较难懂的概念,闭包的形成与变量的作用域以及变量的生命周期密切相关。
1.变量的作用域
var a=1;
var func1=function(){
var b=2;
var func2=function(){
var c=3;
alert(b);//输出:2
alert(a);//输出:1
};
func2();
alert(c);//输出:Uncaught ReferenceError:c is not defined
};
func1();
2.变量的生命周期
<html>
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<scropt>
var nodes=document.getElementsByTagName('div');
for(var i=0,len=nodes.length;i<len;i++){
nodes[i].onclick=function(){
alert(i);
};
};
</script>
</body>
</html>
测试结果:
无论点击哪一个div,弹出的结果都是5,这是因为onclick事件是被异步触发的,触发时,for循环早已结束,i的值已经是5.
解决方法:
for(var i=0,len=nodes.length;i<len;i++){
(function(i){
nodes[i].onclick=function(){
alert(i);
};
})(i)
};
3.闭包的作用
封装变量
可以把一些不需要暴露在全局的变量封装成私有变量
var cache={};
var mult=function(){
var args=Array.prototype.join.call(arguments,',');
if(cache[args]){
return cache[args];
}
var a=1;
for(var i=0,l=arguments.length;i<l;i++){
a=a*arguments[i]
}
return cache[args]=a;
};
alert(mult(1,2,3));//输出:6
alert(mult(1,2,3));//输出:6
避免了多次计算
利用闭包减少全局变量
var mult=(function(){
var cache={};
return function(){
var args=Array.prototype.join.call(arguments,',');
if(cache[args]){
return cache[args];
}
var a=1;
for(var i=0,l=arguments.length;i<l;i++){
a=a*arguments[i]
}
return cache[args]=a;
}
})();
提炼函数后
var mult=(function(){
var cache={};
var caculate=function(){
var a=1;
for(var i=0,l=arguments.length;i<l;i++){
a=a*arguments[i]
}
return a;
};
return function(){
var args=Array.prototype.join.call(arguments,',');
if(cache[args]){
return cache[args];
}
return cache[args]=caculate.apply(null,arguments);
}
})();
延续局部变量的寿命
var report=(function(){
var imgs=[];
return function(src){
var img=new Image();
imgs.push(img);
img.src=src;
}
})();
这样就能解决请求丢失的问题