闭包总结

 

 


闭包的优点:


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 object

eg2、循环闭包

<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);//正确

 

原文地址:https://www.cnblogs.com/taoxiaodan/p/6390602.html