# 六.闭包
前言
- 闭包有两部分组成,一个是当前的执行上下文 A,一个是在该执行上下文中创建的函数 B
- 当 B 执行的时候引用了当前执行上下文 A 中的变量就会产生闭包
- 当一个值失去引用的时候就会标记,被垃圾回收机制回收并释放空间
- 闭包的本质就是在函数外部保持内部变量的引用,从而阻止垃圾回收
- 调用栈并不会影响作用域链,函数调用栈是在执行时才确定,而作用域规则是在代码编译阶段就已经确定了
- MDN 定义:闭包是指这样的作用域
foo
,它包含了一个函数fn
,这个函数fn
可以调用被这个作用域所封闭的变量a
,函数等内容
# 1.认识闭包
Call Stack
为当前的函数调用栈Scope
为当前正在被执行函数的作用域链Local
为当前的活动对象
function one() {
var a = 1
var b = 2
function two() {
var c = 3
debugger
console.log(a, c)
}
return two
}
let two = one()
two()
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
function one() {
var a = 1
var b = 2
function two() {
debugger
console.log(a)
}
two()
}
one()
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 2.闭包优化
- 中间没用到的变量闭包会被忽略
function one() {
var a = 1
function two() {
var b = 2
function three() {
var c = 3
debugger
console.log(a, b, c)
}
three()
}
two()
}
one()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
function one() {
var a = 1
function two() {
var b = 2
function three() {
var c = 3
debugger
console.log(a, c)
}
three()
}
two()
}
one()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 3.arguments
function log(a, b) {
debugger
console.log(a, b)
}
log(1, 2)
1
2
3
4
5
2
3
4
5
典型使用场景
- Vue 源码中,编译函数生成后会保存在内存中,避免频繁编译时重新生成编译函数;派发更新函数同理
- Webpack 源码中,编译函数生成后会保存起来,整个生命周期只执行一次