闭包的官方定义:函数内部的函数
说起闭包,首先要了解函数:
函数的两个步骤:
1.函数的定义;
1-1. 再堆里面开辟一个空间.
1-2. 把函数体内的所有代码当作字符串存储在这个空间中.
1-3. 把空间地址赋值给栈里面的变量(函数名)
函数的调用.
2.函数的调用:
2-1. 按照存储的地址找到 函数存储空间
2-2. 在 调用栈(不是栈内存) 里面再次开辟一个 函数执行空间
2-3. 在函数执行空间内进行 形参赋值
2-4. 在函数执行空间内进行 预解析
2-5. 把 函数存储空间 的代码复制一份拿到 函数执行空间 里面执行
2-6. 代码全部执行完毕, 这个新开辟的函数执行空间销毁
注:定义在函数内部的变量,会随着函数执行完毕,函数执行空间的销毁而销毁.
如何创建一个不会被销毁的函数执行空间:
函数每一次执行会创建一个函数执行空间,当函数内部返回一个 复杂数据类型 ,并且函数外部还有在接收,那么这个函数执行空间不会被销毁.
作用:延长了变量的生命周期
下面展示一些 代码片
。
function fn() {
var num = 100
console.log('hello world')
// 函数内部返回一个复杂数据类型
return {}
}
// obj 接收的 fn 函数执行空间内部的 对象
const obj = fn()
// 创建了一个新的对象返回
const obj2 = fn()
console.log(obj)
综上我们引入闭包的形成条件:
- 一个不会被销毁的函数执行空间
- 函数内部 直接 或者 间接 的返回一个函数
- 内部函数操作(访问,赋值)着外部函数的变量
当这三个条件都满足的时候,我们管内部的函数叫做外部函数的 闭包函数
function fn() {
var num = 100
// fn 函数内部返回了一个 a 函数
return function a() {
// 访问外部函数 fn 的私有变量 num
// 并且把 num 的值返回
return num
}
}
// 此时, res 接收的是 fn 函数内部的 a 函数
// 我们管 res 或者 a 叫做 fn 的闭包函数
const res = fn()
// 返回 100
// fn 函数的私有变量 num
console.log(res())
闭包的作用:
- 保护变量私有化,定义在函数内部的变量就是私有变量.
- 可以利用闭包函数 在函数外部访问函数内部的私有变量.
闭包的特点:
-
保护变量私有化
1-1优点:不去污染全局
1-2缺点:外部不能访问,需要闭包函数 -
可以在函数外部访问函数内部的私有变量
2-1优点:不局限于私有变量
2-2缺点:外部访问需要闭包函数 -
变量的生命周期
3-1优点:变量的生命周期被延长
3-2缺点:生成了一个不会被销毁的函数空间(致命缺点)导致内存泄漏
闭包销毁:
当你想销毁闭包的时候,只要这个不销毁的空间不在了,闭包就没了.
不销毁的空间:返回复杂数据类型 外部有变量接收
销毁空间:外部不再有变量接收 外部接收的变量的变量重新赋值.
function fn() {
var num = 100
return function a() {
return num
}
}
// res 是 fn 的闭包函数
let res = fn()
// res 存储的不再是 fn 函数内部返回的 函数了
// fn 的执行空间销毁了
res = 100