闭包的定义
MDN 对闭包的定义:
闭包是指那些能够访问 自由变量 的 函数。
两个点,首先闭包必须是 函数,其次必须要能访问 自由变量
自由变量指哪些?
自由变量是指在函数中使用的,但既不是函数参数也不是函数内局部变量的变量。
由此,我们可以看出闭包由两部分构成:
闭包 = 函数 + 函数中使用的自由变量
举个例子:
var a = 1
function foo() {
console.log(a)
}
foo()
foo函数可以访问变量a,但是a既不是函数内局部变量也不是参数变量,所以a是一个自由变量。所以,函数foo + 变量a 就构成了一个闭包。
《javaScript权威指南》:从技术的角度来说,所有的javascript函数都是闭包。
这是理论上的闭包,还有一种实践上的闭包:
ECMAScript中,闭包指的是:
- 从理论角度:所有的函数。因为它们在创建的时候都把上层的上下文都保存起来了。哪怕是简单的全局变量都如此,因为函数中访问全局变量就相当于在访问自由变量。
- 从实践角度:以下函数才算是闭包:
- 即使创建它的上下文已经销毁,它仍然存在(比如,内部函数从父函数中返回)。
- 在代码中引用了自由变量。
分析
var data = []
for (var i = 0; i < 3; i++) {
data[i] = function () {
console.log(i);
};
}
data[0]();
data[1]();
data[2]();
很显然,答案都是3,让我们分析一下原因:
当执行到 data[0]()
的时候,
此时全局上下文的VO为,
globalContext.VO = {
data: [...],
i: 3
}
函数 data[0]
的AO和作用域如下,
data[0]Context = {
AO: {
arguments: {
length: 0
}
},
Scope: [AO, globalContext.VO ]
}
我们可以看到,data[0]Context的AO中并没有i值,往上层作用域查找,找到globalContext.VO中