闭包
回答要素:
- 作用域链
- 执行上下文
- 函数的活动对象(即参数)
-
- 函数局部上下文中的叫活动对象,只在函数执行期间存在
- 全局上下文中的叫变量对象,它会在代码执行期间始终存在
- 垃圾回收
定义
闭包的本质其实是一个函数,但是特殊在于这个函数会引用另一个函数作用域中的变量
作用域链
定义
作用域链的本质是什么?是一个包含指针的列表,每个指针分别指向一个变量对象
先来看一个普通函数的作用域链
function compare(value1, value2) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
let result = compare(5, 10);
- 定义compare函数
-
- 创建作用域链,预装载全局变量对象
- 调用compare函数
-
- 装载活动对象,value1和value2
- 定义result变量
- 调用结果复制给result
重点
作用域链决定了各级上下文中的代码在访问变量和函数时的顺序
执行上下文
定义
变量或函数的上下文决定了它们可以访问哪些数据,以及它们的行为
所以说
决定变量或函数可以访问哪些数据,以及他们行为的域就叫做执行上下文
重点
- 上下文在其所有代码都执行完毕后会被销毁,包括定义在它上面的所有变量和函数(全局上下文在应用程序退出前才会被销毁,比如关闭网页或退出浏览器)
- 全局上下文是最外层的上下文
- 每个函数调用都有自己的上下文
垃圾回收
闭包中的变量不会被自动垃圾回收,需要手动清除
正常来说,一个函数执行完之后,会自动回收里面的变量,外部的函数或对象访问不到里面的变量了
var color = "blue";
function changeColor() {
let anotherColor = "red";
function swapColors() {
let tempColor = anotherColor;
anotherColor = color;
color = tempColor;
// 这里可以访问 color、anotherColor 和 tempColor
}
// 这里可以访问 color 和 anotherColor,但访问不到 tempColor
swapColors();
}
// 这里只能访问 color
changeColor();
就比如changeColor访问不到tempColor
闭包的话,比如下面这个例子
const _count = function(){
var num = 1;
return function(){
return num++;
}
}
内部的匿名函数保持着对num的引用,所以num不会被自动回收