闭包是函数的一种高级使用方式,在了解闭包之前,先梳理下函数的两个阶段。
一、函数的两个阶段
1、函数的定义阶段
- 开辟一个存储空间
- 把函数体内的代码当做字符串放在这个存储空间中,函数体的代码中的所有变量都不会进行解析
- 把存储空间的地址给函数名
2、函数的调用阶段
- 按照函数名对应的地址找到函数的存储空间
- 实参形参赋值
- 预解析
- 把函数存储空间中的代码拿出来执行
/*
函数的定义阶段
+ 在内存中开辟一个函数的存储空间xxff00
+ 把函数体中的代码放在这个存储空间中,此时a,b没有进行解析
+ 把xxff00这个地址赋值给fn这个函数名
*/
function fn(a,b){
let s=a + b;
console.log(s);
}
/*
函数的调用阶段
+ 按照fn里面存储的地址,找到xxff00这个函数存储空间
+ 开辟一个函数执行空间(xxff11),在运行内存里面
+ 在xxff11这个执行空间中进行形参赋值
+ 在xxff11这个执行空间中进行预解析
+ 把存储空间xxff00里面存储的代码赋值一份到这个执行空间
+ 等到代码执行完毕后,这个开辟的xxff11执行空间就销毁了
*/
fn(3,5);
二、不会销毁的函数执行空间
一个函数在执行的时候,会开辟一个执行空间,所有的代码都会放在这个执行空间例执行,执行完毕以后,这个函数执行空间就会被销毁。
但当函数内部返回一个“复杂数据类型”,并且在函数外部有变量接收这个复杂数据类型的时候,这个函数的执行空间就不会被销毁。
当外部接收的这个变量不再引用函数内部返回的复杂数据类型时,这个函数空间就会销毁了。
三、闭包
1、闭包生成的三个必要条件:
- 在函数A内部直接或者间接返回另一个函数B
- B函数内部使用A函数里面的私有变量
- A函数外部有一个变量接收函数B
2、闭包空间
- 我们把这个不会被销毁的A函数的执行空间叫做闭包空间
- 把函数A里面返回的函数B叫做函数A的闭包函数
- 官方定义:闭包==>函数内部的函数
3、闭包的特点
- 延长了变量的生命周期,因为执行空间不销毁,变量也没有被销毁
- 可以访问函数内部的私有变量
- 保护私有变量(只要是函数都有这个特点)