关于JavaScript闭包概念的通俗解释
JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里。
所有的函数在运行时都会在其所在空间创建一个新的子平行空间,所有的参数,局部变量及在函数内创建的函数(不管是函数声明还是赋值给变量的函数表达式),都是在这个子平行空间内创建(出生)的,只有出生在这个平行空间内的代码可以访问到这个平行空间内的变量及函数。
即使在这个空间内创建的函数被返回,并赋值给全局或者父平行空间的变量,它也还是出生在那个平行空间,它对变量的访问也还是从那个空间开始往更大的平行空间查找变量,直到全局变量。由于平行空间内的函数在运行时又会在其所在空间创建更小的平行空间。所以如果在平行空间内创建的函数还有可能运行,则函数所在的平行空间及所有父空间都不会被销毁。
下面来画个图:
var a = 1
function f(b) {
return function g(c) {
return function h(d) {
return a + b + c + d
}
}
}
var add2 = f(2)
var add4 = add2(2)
var add5 = add2(3)
var r1 = add4(10)
var r2 = add5(10)
console.log(r1,r2)
左边是代码
1. 最大的黑框是全局空间,然后第11行的 f 运行时创建了较小的黑色框,并传入了2即形参b的值,用红色圈出来了,
2. 同时 f 的运行返回了函数g,被全局空间内的变量add2指向,add2再次调用两次,于是在较小的黑框空间内又创建出了两个空间,即两个蓝色的空间,
3. 传入的c分别为2和3,也在空间内画出并用红色圈出来了,同时函数g两次调用都返回了函数h,分别赋给了变量add4和add5,
4. 但注意add4和add5分别指向了从不同空间(即g两次运行时创建的两个空间),这两个函数是不同的,而且也处于不同的空间。
r1 = 15 , r2 = 16
HTML 也好,JS 语言也好,还是空间结构也好,都同为树状结构。
而观察前面的图会发现,高阶函数运行过程中创建的嵌套作用域也是树状结构。最后,这个平行空间如果没被销毁的话,就形成了闭包;而变量从内层空间向外层空间查找的过程则是作用域链(Scope Chain)。
作者:谢然
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。