每次调用javascript函数的时候,都会为之创建一个新的对象用来保存局部变量,把这个对象添加至作用域链中。
当函数返回的时候,就从作用域链中将这个绑定变量的对象删除。如果不存在嵌套的函数,也没有其他引用指向这个绑定对象,它就会被当做垃圾回收掉。
如果定义了嵌套的函数,每个嵌套的函数都各自对应一个作用域链,并且这个作用域链指向一个变量绑定对象,但如果这些嵌套的函数对象在外部函数中保存下来,那么它们也会和所指向的变量绑定对象一样当做垃圾回收。
但是如果这个函数定义了嵌套的函数,并将它作为返回值返回或者存储在某处的属性里,这时就会有一个外部引用指向这个嵌套的函数。它就不会被当做垃圾回收,并且它所指向的变量绑定对象也不会被当做垃圾回收。
1.什么是闭包?
简单的说,就是函数嵌套函数,
内部函数可以引用外部函数的参数和变量
参数和变量不会被垃圾回收机制所回收
Eg:
function aaa( ){
var a=5;
function bbb( ){
console.log( a );
}
return bbb;
}
var c=aaa();
c();//5
闭包的优点?
(1)希望或者说可以使一个变量长期驻扎在内存当中
(2)避免全局污染
首页看一个全局变量的例子:
eg:
var a=1;
function aaa(){
a++;
console.log(a);
}
aaa();//2
aaa();//3
然后把这个变量变成局部变量来看一下:
function aaa(){
var a=1;
a++;
console.log(a);
}
aaa();//2
aaa();//2
接下来咱们改成闭包:
function aaa() {
var a=1;
return function(){
a++;
console.log( a );
}
}
var b=aaa();
b();//2
b();//3
还可以这样写:
var aaa=( function( ) {
var a=1;
return function(){
a++;
console.log(a);
}
} ) ( );
aaa();//2
aaa();//3
那闭包用在哪里呢?看下面例子
(1)模块化代码
var aaa=( function(){
var a=1;
function bbb() {
a++;
console.log( a );
}
function ccc() {
a++;
console.log( a );
}
return {
b:bbb,
c:ccc
}
} )( );
aaa.b();//2
aaa.c();//3
aaa.ccc();//报错
继续往下看:
(2)在循环中直接找到对应元素的索引
eg: <ul>
<li>11</li>
<li>11</li>
<li>11</li>
</ul>
window.onload=function() {
var aLi=document.getElementsByTagName( li );
for( var i=0; i< aLi.length; i++){
aLi [ i ].onclick=function(){
alert(i);//连续弹出三次3
}
}
}
上面没有达到闭包效果,那么怎么改写呢?看下面
window.onload=function() {
var aLi=document.getElementsByTagName( ‘li’ );
for( var i=0; i< aLi.length; i++){
( function( i){
aLi [ i ].onclick=function( ){
alert(i);//连续弹出三次,分别0 1 2
}
} )( i );
}
}
还可以这样改写:
window.onload=function() {
var aLi=document.getElementsByTagName( ‘li’ );
for( var i=0; i< aLi.length; i++){
aLi [ i ].onclick=(function( i ){
return function(){
alert(i);//连续弹出三次,分别0 1 2
}
})( i );
}
}
闭包注意的地方?继续往下看
在IE浏览器会出现或引起内存泄露,如何解决?
eg:
<div id=” d1”> 555</div>
window.onload=function () {
var oDiv=document.getElementById(‘d1’);
oDiv.onclick=function(){ //变量引用内部函数
alert(oDiv.id); //内部函数引用外部对象
}
//这时候就会出现内存泄露,应该这样解决
window.onunload=function(){
oDiv.omclick=null;
}
}
还可以这样解决:
window.onload=function () {
var oDiv=document.getElementById(‘d1’);
var id=oDiv.id;
oDiv.onclick=function(){
alert(id);
}
oDiv=null;
}
}