闭包的优点:
1、匿名自执行函数,模拟块级作用域,避免污染全局变量
(function(){ var a=100; function F1(){ alert(a); } function F2(){ alert(a); } F1(); //100 F2(); //100 })(); alert(a)
2、缓存
function f(){ var a=100; return function(){ a++;alert(a);} } var F=f(); F();//101 F();//102
3 、实现封装
function Person(){ var a = 100; this.get=function(){ return a; }; } var P=new Person(); alert(P.get());
闭包的缺点:
1.占用内存
通常来说,函数的活动对象会随着执行期上下文一起销毁,但是,由于闭包引用另外一个函数的活动对象,因此这个活动对象无法被销毁,这意味着,闭包比一般的函数需要更多的内存消耗。
2.内存泄露
由于IE使用非原生javascript对象实现DOM对象,因此闭包会导致内存泄露问题,例如:在IE9之前,如果闭包的作用域链中保存着一个HTML元素,那么意味着该元素无法被销毁。
/*这里DOM对象element引用闭包函数,闭包函数作用域引用DOM对象,循环引用导致内存泄露。*/ function closure(){ var element=document.getElementById("elementID"); element.onclick=function(){ alert(element.id); } } /*解决方法:先把element.id用局部变量id保存起来,并且在闭包中引用该变量消除了循环引用。但是,这样还不能消除内存泄露,闭包会引用包含函数的活动变量,而其中会有element。即使闭包闭包不直接引用element,包含函数的活动对象仍然会保存一个引用,因此有必要把element设为null。*/ function closure(){ var element=document.getElementById("elementId"); var id=element.id; element.onclick=function(){ alert(id); } element=null; }3.性能问题
使用闭包时,会涉及到跨作用域访问,每次访问都会导致性能损失。
因此在脚本中,最好小心使用闭包,它同时会涉及到内存和速度问题。不过我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响。
例子:
eg1、this指向
//this对象是在运行时基于函数的执行环境绑定的。 var name="Window"; var object={ name: "my object", getName: function(){ return function(){ return this.name; } } } alert(object.getName()()); //window /*每个函数被调用时都会取得两个特殊变量:this和arguments。内部函数搜索这两个变量时,只会搜索到其活动对象为止,因此,不可能直接访问外部函数的这两个变量。不过将外部作用域中的this保存在一个闭包能够访问的变量里,就可以访问该对象了。*/ var name="window"; var object={ name : "my object", getName:function(){ var that=this; return function(){ return that.name; } } } alert(object.getName()()); //my objecteg2、循环闭包
<div class="clickBox">1</div>
<div class="clickBox">2</div>
<div class="clickBox">3</div>
<div class="clickBox">4</div>
<div class="clickBox">5</div>
<div class="clickBox">6</div><script type="text/javascript">
var clickBoxs = document.querySelectorAll(‘.clickBox‘);
for (var i = 0; i < clickBoxs.length; i++){
/*
clickBoxs[i].onclick = function(){console.log(i);};//问题
clickBoxs[i].onclick = (function(i){return function(){console.log(i);};})(i);//解决1
*/
clickBoxs[i].onclick =f(i);//解决2.1
}
function f(i){return function(){console.log(i);};}//解决2.2
</script>eg3.在函数执行之前为要执行的函数提供具体参数:settimeout
var a=222; //不传参数时 setTimeout(function(){alert(a)},500);//正确 //传参数时 setTimeout(function(a){alert(a)},500);//undefined,传参失败 function f(obj){alert(obj)} setTimeout(f,500);//undefined,传参失败 setTimeout(f(a),500);//参数无效,传参失败 //正确做法,使用闭包 function F(obj){return function(){alert(obj)}} var f=F(a); setTimeout(f,500);//正确