闭包的概念
闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的方式,就是在一个函数内部返回一个匿名函数。
function test() {
var num = 0;
return function () {
num++
console.log(num);
};
}
test()();//1
内存泄漏
内部函数被外部函数包含时,内部函数会将外部函数的局部活动对象添加到自己的作用域链中。而由于内部匿名函数的作用域链在引用外部包含函数的活动对象 ,即使test执行完毕了,它的活动对象还是不会被销毁!
根据垃圾回收机制,被另一个作用域引用的变量不会被回收。
所以,除非内部的匿名函数解除对活动变量的引用(解除对匿名函数的引用),才可以释放内存。
function test() {
var num = 0;
return function () {
num++
console.log(num); // 这样会导致闭包引用外层的num,当执行完num后,num无法释放
};
}
// 改为
function test() {
var num = {
val: 0
};
return function () {
num.val++
console.log(num.val);
};
num = null // 将num设置为null之后,num.val无法取到,则垃圾回收机制会回收掉num
}
结论
许多人对闭包和内存泄露的关系有误解,认为闭包一定会引起内存泄漏,其实是不对的,我来谈谈我对他们关系的理解。闭包和内存泄露有关系的地方是,使用闭包的同时比较容易形成循环引用,如果闭包的作用域链中保存着一些DOM节点,这时候就有可能造成内存泄露。这主要是程序员容易引起的bug,不是浏览器的问题。
如果要解决循环引用带来的内存泄露问题,我们只需要把循环引用中的变量设为null即可。将变量设置为null意味着切断变量与它此前引用的值之间的连接。当垃圾收集器下次运行时,就会删除这些值并回收它们占用的内存。