(转)深入理解闭包
继续上次闭包的经典文章Javascript Closures的研读。这次学到了“作用域链与函数内部[[scope]]”一节。继续以原文翻译+自己理解的方式呈现文章内容。
作用域链与函数内部[[scope]]正如上节提到的那样,一个函数调用会创建一个执行上下文,而这个执行上下文中包含一个作用域链。在这个作用域链的最开始部分是执行上下文的Activation/Variable对象,后面紧接着就是函数对象自身的[[scope]]
属性,因此很有必要去了解函数内部的这个[[scope]]
属性如何定义的。
在ECMAScript规范中,函数实际也是对象。这些函数对象要么是“函数申明(function declarations)”方式的函数——在变量实例化阶段创建的,要么是“函数表达式(function expressions)”——在执行阶段创建的,要么是“函数构造器(Function
constructor)”——在调用实例化时创建。
这里比较特殊需要注意的是,使用“函数构造器(Function
constructor)”创建的函数对象的[[scope]]
属性只包含全局对象。
而使用“函数申明(function declarations)”或者“函数表达式(function expressions)”创建的函数对象,其[[scope]]
属性包含了创建该函数的那个父函数(或者全局对象)的执行上下文(译者注:可能这里有些绕,不大容易理解,不过下面会有详细解释,这里大概有这样一种概念就好)。
例如最简单的全局函数声明:
从图中很容易发现,如果在不存在with
语句时,函数对象的[[scope]]
属性与外层函数(或者全局对象)的执行上下文有着密切的联系,这种联系也就形成了作用域链,建立了内外函数的沟通桥梁,这样也便很容易理解为什么内层函数可以访问外层函数局部变量,反之则不行。
?