什么是闭包
一般我们说有有个 function a 里面包含并返回里 function b 这个函数 b 就是闭包函数。闭包可以重用一个对象,并保护对象不被串改和污染。
function foo() {
let a = 1;
return function far() {
console.log('-----------------------------', a);
}();
}
foo()
作用域和作用域链
作用域:就是在代码运行的过程中,有些变量,函数,对象有自己独立的可访问性,例如上例中的 变量a在函数foo中才能访问,在函数外部是不能访问的。函数作用域形成了一个独一的范围,保护了域内的变量,有效的防止了变量污染。
作用域链:通俗来说就是在作用域中,访问变量,遵循就近原则。变量的查找,会一层一层向上寻找,找到就停止,找不到就报错,新城了一个链条。
let a = 3;
function foo() {
let a = 1;
let b = 2;
return function far() {
return function result() {
console.log('-----------------------------', a);
}();
}();
}
foo()
// ----------------------------- 1
let a = 3;
function foo() {
let b = 2;
return function far() {
return function result() {
console.log('-----------------------------', a);
}();
}();
}
foo()
// ----------------------------- 3
在这个例子中如果在foo里有变量a直接得到1,若果没有就向上寻找得到3,如果顶层中也没有就会报错。
闭包的原理
根据js的执行机制,在运行程序的时候会创建一个ao:active object 是函数运行的时候创建的临时活动对象。里面包括了所有的局变量,参数,this等。在运行上下文的时候就会被销毁,被垃圾回收机制回收。所以为了有些数据不被销毁,就要使用闭包。
let a = 3;
function foo() {
let a = 1;
let b = 2;
return function far() {
return a;
};
}
function fn1() {
let res = foo();
console.dir(res)
}
fn1()
a就没有被回收。
闭包的使用
因为闭包可以保存变量等原因,闭包被运用在防抖和截流中,因为闭包可以保护内部变量,也常用来模拟对象的私有写法。
function fn1() {
let a = 0;
let b = 0;
return {
add: function() {
a++;
},
sub: function() {
a--;
},
val: function() {
return a;
}
}
}
let res1 = fn1();
let res2 = fn1();
console.log('-----------------------------', res1.val());
res1.add()
res1.add()
console.log('-----------------------------', res1.val());
console.log('-----------------------------', res2.val());
// ----------------------------- 0
// ----------------------------- 2
// ----------------------------- 0
闭的缺点
因为闭包能保护变量,导致变量不能被js的垃圾回收机制及时回收,容易占用内存,消耗资源,产生内存泄漏。所以不能滥用。