1.什么是闭包?
(1)函数嵌套函数
(2)内部函数可以引用外部函数的参数和变量
(3)参数和变量不会被垃圾回收机制所收回。因为内部函数bbb还在被引用着,所以需要长期驻扎在内存中。
function aaa(a){
var b=5;
function bbb(){
alert(a);
alert(b);
}
}
aaa();//a和b都是可以访问的到的
这就是闭包
function aaa(){
var a = 5;
function bbb(){
alert(a);
}
return bbb;
}
var c = aaa();//因为aaa()函数返回的是bbb
c();//此时c()就相当于bbb()
返回的结果就是:5
2.什么是垃圾回收机制?
//JS中的垃圾回收机制
function aaa(){
var a = 1;
}
aaa();
变量a会被JS中垃圾回收机制收回,就不存在了。
3.闭包有什么好处?应用在哪里?
好处:(1)希望一个变量长期驻扎在内存当中
(2)避免全局变量的污染
(3)私有成员的存在
栗子1:全局变量的污染:a是全局变量
var a = 1;
function aaa(){
a++;
alert(a);
}
aaa(); //2
aaa(); //3
alert(a);//3
栗子2:此时a是局部变量,每执行一次,就进入垃圾回收机制,所以每次执行aaa()函数,结果都是2
function aaa(){
var a = 1;
a++;
alert(a);
}
aaa(); //2
aaa(); //2
栗子3:利用闭包,变量a是局部变量
function aaa(){
var a=1;
return function(){
a++;
alert(a);
}
}
var b=aaa();
b(); //2
b(); //3
alert(a); //a is not defined,因为a不是全局变量,访问不到a
用法:
1.模块化代码
2.在循环中直接找到对应元素的索引
栗子4:模块化代码
function aaa(){
alert(1);
}
aaa();
//这两个函数结果是一样的,不同的是下面的(function(){
alert(1);
})是一个函数表达式
(function(){
alert(1);
})();
var aaa=(function(){
var a=1;
return function(){
a++;
alert(a);
}
})();
aaa(); //2
aaa(); //3
栗子5:有私有成员的存在,变量a,函数bbb(),函数ccc()
var aaa=(function(){
var a=1;
function bbb(){
a++;
alert(a);
}
function ccc(){
a++;
alert(a);
}
return {
b:bbb,
c:ccc
}
})();
aaa.b(); //2
aaa.c(); //3,为什么是3呢?因为a相对于bbb函数和ccc函数,是全局变量,所以函数bbb执行后,a=2了,再执行ccc函数就是3了
栗子6:在循环中直接找到对应元素的索引
方法一:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>无标题文档</title> <script> window.onload = function(){ var aLi = document.getElementsByTagName('li'); for(var i=0;i<aLi.length;i++){ (function(i){ aLi[i].onclick=function(){ alert(i); } })(i);//将i参数传进去,存在内存中。 } }; </script> </head> <body> <ul> <li>11111111111</li> <li>11111111111</li> <li>11111111111</li> </ul> </body> </html>
这样得到的结果是,点击哪一个按钮,就弹出那个位置的索引
方法二:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>索引</title> <script> window.onload=function(){ var lis=document.getElementById('test').getElementsByTagName('li'); for(var i=0;i<lis.length;i++) { lis[i].index=i; lis[i].onclick=function(){ alert(this.index); }; } } </script> </head> <body> <ul id="test"> <li>这是第一条</li> <li>这是第二条</li> <li>这是第三条</li> </ul> </body> </html>
4.闭包需要注意的地方?
在IE下有可能闭包引发的内存泄露问题及解决方案
内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
memory leak会最终会导致out of memory!
内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。
内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出!比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出.
栗子7:这样就会引发内存泄漏,除非关掉浏览器。
window.onload = function(){ var oDiv = document.getElementById('div1'); oDiv.onclick = function(){ alert(oDiv.id); };
为什么这样会引发内存泄漏?
因为dom已经获取到了div1的节点,下面的oDiv的属性onclick里面的函数又存在访问oDiv的属性id,这样就形成了内存泄漏。
解决方案:
第一种:
window.onload = function(){
var oDiv = document.getElementById('div1');
oDiv.onclick = function(){
alert(oDiv.id);
};
window.onunload = function(){
oDiv.onclick = null;
};
};
onunload 事件在用户退出页面时发生。页面退出时,将onclick属性释放。
第二种:将需要用的id先获取到,最后将oDiv释放。
window.onload = function(){
var oDiv = document.getElementById('div1');
var id = oDiv.id;
oDiv.onclick = function(){
alert(id);
};
oDiv = null;
};