一、什么是闭包
1、父函数里面嵌套的子函数,子函数访问父函数的局部变量。
2、通过return将子函数暴露到全局作用域,子函数就形成闭包。
3、通过闭包,父函数的局部变量没有被销毁,可通过闭包去调用 ,但同时,这个局部变量也不会被全局变量污染。
二、为什么需要闭包
因为局部变量无法共享和长久的保存,而全局变量可能造成变量污染,所以我们希望有一种机制既可以长久的保存变量又不会造成全局污染。
三、一个简单的闭包
function addNum() {
var num = 0;
return function () {
num++
console.log(num);
};
}
addNum()();//1
//简单点就是return一个函数,此时外部可以获取局部作用域里的num
四、闭包的优点和缺点
优点: 避免全局变量的污染,同时,局部变量没有被销毁,驻留在内存中,还可以被访问。
缺点: 使用不当,会造成内存泄露,注:老浏览器(主要是IE6)由于垃圾回收有问题导致很容易出现内存泄漏,现在的主流浏览器已经不会发生这种问题。
五、关于内存泄漏
许多人对闭包和内存泄露的关系有误解,认为闭包一定会引起内存泄漏,其实是不对的,我来谈谈我对他们关系的理解。闭包和内存泄露有关系的地方是,使用闭包的同时比较容易形成循环引用,如果闭包的作用域链中保存着一些DOM节点,这时候就有可能造成内存泄露。这主要是程序员容易引起的bug,不是浏览器的问题。
如果要解决循环引用带来的内存泄露问题,我们只需要把循环引用中的变量设为null即可。将变量设置为null意味着切断变量与它此前引用的值之间的连接。当垃圾收集器下次运行时,就会删除这些值并回收它们占用的内存。
比如:
function showId() {
var el = document.getElementById("app")
el.onclick = function(){
console.log(el.id) // 这样会导致闭包引用外层的el,当执行完showId后,el无法释放
}
}
// 改成下面
function showId() {
var el = document.getElementById("app")
var id = el.id
el.onclick = function(){
console.log(id) // 这样会导致闭包引用外层的el,当执行完showId后,el无法释放
}
el = null // 主动释放el
}