JavaScript中,JavaScript里一切都是对象,包括函数。函数对象和其它对象一样,拥有可以通过代码访问的属性和一系列仅供JavaScript引擎访问的内部属性。其中一个内部属性是作用域,包含了函数被创建的作用域中对象的集合,称为函数的作用域链。
作用域(scope)
通常来说一段程序代码中使用的变量和函数并不总是可用的,限定其可用性的范围即作用域,作用域的使用提高了程序逻辑的局部性,增强程序的可靠性,减少名字冲突。
作用域链(scope chain)
作用域链决定了哪些数据能被函数访问。当一个函数创建后,它的作用域链会被创建此函数的作用域中可访问的数据对象填充。
当某个函数被调用时,会创建一个执行环境及相应的作用域链。然后,使用arguments和其他命名参数的值来初始化函数的活动对象。但在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数对象处于第三位……直至作为作用域终点的全局执行环境
作用域链的前端始终是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象作为变量对象。活动对象在最开始时只包含一个变量,即arguments对象。作用域链的下一个变量对象来自包含环境,而在下一个变量对象则来自下一个包含环境。这样一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象。
这里面有很多概念,比如什么是执行环境、变量对象等。
执行环境(Execution Context)
执行环境是JavaScript中的重要概念之一。执行环境定义了变量或函数有权访问的其他数据,决定了他们各自的行为。每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。
全局执行环境是最外围的一个执行环境。在Web浏览器中,全局执行环境被认为是window对象,因此所有全局变量和函数都是作为window对象的属性和方法创建的。某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁(全局执行环境知道应用程序退出–例如关闭网页或浏览器—时才会被销毁)
每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行后,栈将其环境弹出,把控制权返回给之前的执行环境。
执行环境的建立分为两个阶段:进入执行上下文(创建阶段)和执行阶段(激活/执行阶段)
(1)进入上下文阶段:发生在函数调用时,但在执行具体代码之前。具体完成创建作用域链;创建变量、函数和参数以及求this的值
(2)执行代码阶段:主要完成变量赋值、函数引用和解释/执行其他代码
总的来说可以将执行上下文看作是一个对象
变量对象(Variable Object)
每一个执行环境都对应一个变量对象,在该执行环境中定义的所有变量和函数都存放在其对应的变量对象中。
(1)进入执行上下文时,VO的初始化过程如下:
函数的形参:变量对象的一个属性,其属性名就是形参的名字,其值就是实参的值;对于没有传递的参数,其值为undefined;
函数声明:变量对象的一个属性,其属性名和属性值都是函数对象创建出来的,如果变量对象已经办好了相同名字的属性,则替换它的值
变量声明:变量对象的一个属性,其属性名即为变量名,其值为undefined;如果变量名和已经声明的函数名或者函数的参数名,则不会影响已经存在的属性
(2)执行代码阶段,变量对象中的一些属性undefined值将会确定
网友评论