先看一段代码:
var global
function a() {
function b() {
var bb = 123
aa = 0
}
var aa = 123
b()
}
a()
想一下,代码从上往下执行预编译时,在a定义的时候,作用域链是怎样的?
此时 a在全局对象中,并且因为没有执行,内部没有东西。
a开始执行:
a的作用域链应该如下:
a()执行时,解析进入a函数,此时:
作用域链首位变成了a局部变量。
b函数定义时:
进入b后
b函数开始执行时:
b执行完成后,作用域链被销毁,意思就是将上图中的所有线都剪断,待a函数下一次执行,会将上面的线重新连起来,重复上述过程:
理解了上面,闭包就很简单了。
再看下一段代码:
var global
function a() {
var aa = 123
function b() {
var bb = 234
console.log(aa)
}
return b
}
var res = a()
res()
仔细分析,作用域链和前文类似:
很显然a执行产生的作用域链和b定义产生的作用域链它们是一样的,a执行完毕后,它与scope chain连接的线被剪断,但是它执行后返回的b被保存到了res中! 所以b的线并没有被剪断,b仍然可以根据作用域链访问到aa这个变量,当然也能输出 “123”.这就产生了闭包。