js闭包(closure)
闭包原理:js中,子函数可以访问父函数的局部变量。
闭包是什么?
在函数内部再声明一个函数,调用父函数的局部变量,就形成了闭包。
function fn() {
let i = 0;
(function fn1() { // <= fn1就是闭包
console.log(i); // console: 0
})();
}
fn
的变量i
,对于fn1
来说是可见的,所以fn1
访问到了i
;
fn1
就是一个闭包。
闭包的作用
闭包最常用的场合,就是读取函数的内部变量,并且让这些变量的值始终保存在内存中,而不与其他全局变量冲突,我们可以用它做某个函数内部变量的setter或getter;
function fn() {
let i = 0;
function fn1() { // <= 闭包fn1
i++;
console.log(i);
}
return fn1; // 返回闭包fn1
}
let res = fn(); // res <= fn1
res(); // console: 1
res(); // console: 2
res(); // console: 3
可以发现,虽然i
是fn
的局部变量,但它并没有在内存中被回收,而是一直存在于内存中的,
连续执行了三次闭包,如果它被回收了,那么结果应该是三次1,
但结果是i
做了累加,说明i
没有被销毁。
这是为什么呢?
闭包被赋给了一个全局变量res
,这导致闭包fn1
一直被存在内存中,而fn1
的存在依赖于父函数fn
,所以fn
每次执行后并没有被销毁,i
也就没有被销毁。
!!attention!!
由于闭包会使父函数中的局部变量一直保存在内存中,内存消耗是相当大的,所以不要大量使用闭包,否则会有严重的性能问题,在IE中可能导致内存泄漏;
应在退出函数前,将不要的局部变量删除;
或在使用完闭包后,将储存闭包的变量删除。