1、什么是闭包?
概念:1、函数中返回一个函数;2、函数的声明的作用域和函数使用的作用域不同
可以理解为能够读取其它函数内部变量的函数。
通过函数实现变量私有化,同时可以让外部访问内部的资料
let num1 = 7;
function test2() {//返回的是一个function
let num2 = 8;
console.log(num1);//7
function getNum() {
return num2;
}
return getNum;
}
let result = test2();
console.log(result());//8
本质:将函数内部和外部连接起来的一座桥梁
目的:解决函数外部想获取到函数内部的局部变量
缺点:1、需要手动释放资源;2、过多的闭包,会造成程序变慢(操作不当容易造成内存溢出)
用途:1、实现变量私有化;2、读取函数内部的变量;3、让函数内部的变量始终保持在内存中
function clourse() {
let a = 10;//保存在内存中,没有被摧毁掉
console.log(a);//10
function add() {
a++;
console.log(a);
}
return add;
}
let addFun=clourse();//10
console.log(addFun());//11
console.log(addFun());//12
console.log(addFun());//13
2、闭包原理
函数在执行的时候会分成两个阶段:预编译阶段和执行阶段
- 在预编译阶段,如果发现函数内部使用了外部函数的变量,则会在内存中创建一个“闭包”对象并保存对应变量的值,如果已存在“闭包”,则只需要增加对应属性值即可;
- 执行完成后,函数执行上下文会被销毁,函数对“闭包”对象的引用也会被销毁,但是内部函数还持用该“闭包”的引用,所以内部函数可以继续使用“外部函数”中的变量;
- 利用了函数作用域链的特效,一个函数内部定义的函数,会将包含外部函数的活动对象添加到它的作用域链中,函数执行完毕,其执行作用域链销毁,但是因为内部函数的作用域链仍在引用这个活动对象,所以其活动对象不会被销毁,直到内部函数被销毁后才会被销毁。
3、如何手动释放?
res=null;
原理:没有变量引用它,则会被当垃圾进行回收
4、闭包的嵌套
//对于test放来说,test1是闭包
//对于test1放来说,test2是闭包
function test() {
console.log('test');
function test1() {
console.log('test1');
function test2() {
console.log('test2');
}
return test2;
}
return test1
}
// 访问test2
test()()();//test,test1,test2
/* let t1 = test();//返回test1这个函数 test
let t2 = t1();//返回test2这个函数 test1
t2();//执行test2这个函数 test2*/
5、闭包的使用场景
使用场景:防抖、节流;
链接: js中如何实现防抖、节流?