一、闭包概念:函数嵌套函数,内部函数就是闭包。
1、闭包的经典例子:(如下)*
function outerFun(){
let a = 10;
function innerFun(){
console.log(a);
}//a可访问外部函数变量的
return innerFun;
}
let fun = outerFun();
fun();//打印10
2、注:但正常情况下,函数执行完成,内部变量会被销毁(销毁:释放内存空间)
例子:
function fun(){
let a = 10;
console.log(a);
}
fun()//调用函数执行完之后,该函数内部的局部内存空间就会被释放
console.log(a);//因此在外面不能调用a内部变量,内部函数执行完之后a就被释放了
3、补充:作用域链概念:
let a = 10;
let b = 20;
function fun (){
let a = 30;
let c = 40;
function fun(){
let a = 50;
let d = 60;
}
}
由图可见,作用域链是指在若在内部函数打印某一变量,会一层层的向上查找进行打印,直至找到为止。
4、再回头看刚开始我们说的闭包的经典例子
function outerFun(){
let a = 10;
function innerFun(){
console.log(a);
}//a可访问外部函数变量的
return innerFun;
}
let fun = outerFun();
fun();//打印10
该段代码执行到倒数第二行let fun = outerFun()时候,innerFun()内部函数并没有执行完成,而是innerFun()作为返回值赋值给了fun,然后fun就是innerFun,fun就没有执行完成,还可以再次调用innerFun。(可见还可以调用内部函数innerFun,因此外部函数let a = 10 就不会被销毁)
5、总结:因此,可见闭包内部函数没有执行完成, 外部函数变量就不会被销毁。
二、闭包应用
1、闭包可以封装一段代码
let a = 10;
let b = 20;
function add(){
return a+b;
}
function sub(){
return a-b;
}
let result1 = add();
let result2 = sub();
console.log(result1);
console.log(result2);
2、可见此段代码比较冗余,我们可以使用闭包进行封装。
//定义一个立即执行函数
let yzk = (function(){
let a = 10;
let b = 20;
function add(){
return a + b;
}
function sub(){
return a-b;
}
//返回一个对象
return {
add:add,
sub:sub
}
})()
这样yzk这个模块就是一个对象,并且它有两个属性add和sub
可以使用这个对象去调用这两个函数。
let result1 = yzk.add();
let result2 = yzk.sub();
console.log(result1);
console.log(result2);
//此时a和b为局部变量外部无法进行访问,只能访问return返回暴露出去的的add和sub。
//可见利用闭包实现了模块化的功能。