闭包的概念:
闭包就是一种函数的保护/保存机制。
所谓保护,就是在函数执行的时候,会生成私有上下文,在私有上下文中申明的变量或者函数,会受到私有上下文的保护,不受外界影响;
所谓保存,就是说私有上下文中所创建的堆内存,被当前私有上下文以外的变量所占用,那么当前私有上下文就得不到释放,这就是常说的闭包。
闭包的优点:
防止变量全局污染,封闭作用域,防止受到外界影响
闭包的缺点:
内存泄漏,占用内存较大,影响页面渲染
大家不妨打开控制台试试下面代码,运行结果是否如你所想
//lg1
var a = 10,
b = 11,
c = 12;
function test(a) {
a = 1;
var b = 2;
c = 3;
}
test(10);
console.log(a, b, c);
//lg2
var a = 4;
function b(x, y, a) {
console.log(a);
arguments[2] = 10;
console.log(a);
}
a = b(1, 2, 3);
console.log(a);
//lg3
var a = 9;
function fn() {
a = 0;
return function (b) {
return b + a++;
}
}
var f = fn();
console.log(f(5));
console.log(fn()(5));
console.log(f(5));
console.log(a);
闭包的底层原理:(场景千变万化,掌握原理才是王道,建议与生命周期,作用域,预编译等相关联知识混合食用)
前置知识点:
1.变量的生命周期
全局变量需等到浏览器关闭页面后才结束生命周期
局部变量,等到局部函数执行完毕就结束生命周期
2.垃圾回收机制
当一个变量声明周期结束之后它所指向的内存就应该被释放掉
js按照固定的时间间隔,找到不再使用的变量,释放其占用的内存
目前各大浏览器遵循两个策略
1.标识清除
垃圾回收机制在运行的时候会给存储在内存中的各变量设置一个标记,
2.引用计数
实质上就是跟着一个值的引用次数,当引用次数为0,则就会被回收
当声明一个变量,并将一个引用类型赋值给该变量时,就给该变量的引用次数+1,当变量指向其他一个值的时候,次数-1
function test() {
var a = {}; // a的引用次数为0
var b = a; // a的引用次数加1 为1
var c = a; // a的引用次数再加1 为2
b = {}; // a的引用次数减1 为1
}
注:若存在引用关系,则不会被回收
3.执行上下文(EC)
函数调用会形成执行上下文,执行上下文会被放到执行上下文栈(ECS),也叫函数调用栈(call Stack)
4.变量对象
...