闭包:
函数执行过程中,会形成一个全新的私有上下文,此时会产生两个机制:
(1)保护:保护自己的私有变量不受外界干扰(操作自己的私有变量和外界没有关系);
(2)保存:如果当前上下文不被释放【只要上下文中的某个东西被外部占用即可】,则存储的这些私有变量也不会被释放,可以供其下级上下文中调取使用,相当于把一些值保存起来了;
我们把函数执行带来的两大作用/机制,称为闭包。
闭包不是任何代码格式,而是函数运行的机制。【从本质讲,函数执行形成的上下文没有释放前,都是闭包,只不过大多数函数执行完后,上下文都释放掉了,有人认为这不是闭包。】
市面上多认为:只有上下文不被释放,才是闭包,因为这样才保留下来了。
let x = 1;
function A(y) {
let x = 2;
function B(z) {
console.log(x + y + z);
}
return B;
}
let C = A(2);
C(3);
1、项目中,如果存在大量不被释放的内存(堆/栈/上下文),页面性能会变得很慢。当某些代码操作不能被合理释放,就会造成 前端内存泄漏【高程3】。我们尽可能减少使用闭包,因为它会消耗内存。
2、浏览器垃圾回收机制/内存收机制
谷歌:“查找引用”,浏览器不定时去查找当前内存的引用,如果没有被占用了,浏览器会回收它;如果被占用,就不能回收。
IE:“引用计数法”,当前内存被占用一次,计数累加1次,移除占用就减1,减到0时,浏览器就回收它。
3、优化手段:内存优化
手动释放:取消内存的占用即可。
(1)堆内存:
fn = null 【null:空指针对象】
f = null
(2)栈内存:
把上下文中,被外部占用的堆的占用取消即可。
练习题1
let x = 5;
function fn(x) {
return function (y) {
console.log(y + (++x));
}
}
let f = fn(6);
f(7); // 14
fn(8)(9); // 18
f(10); // 18
console.log(x); // 5
练习题2
let a=0,
b=0;
// 外层的函数A里面的匿名函数被外层的函数A外面引用,所以没有return,也是闭包
function A(a){
A = function(b){
alert(a+b++);
};
alert(a++);
}
A(1);
A(2);