执行环境
执行环境是一个概念,一种机制,它定义了变量或函数是否有权访问其他数据
在javascript中,可执行的JavaScript代码分三种类型:
- Global Code,即全局的、不在任何函数里面的代码,例如:一个js文件、嵌入在HTML页面中的js代码等。
- Eval Code,即使用eval()函数动态执行的JS代码。
- Function Code,即用户自定义函数中的函数体JS代码。
这里我们说全局变量和函数执行环境
1.全局环境
全局环境是最外围的一个执行环境。全局执行环境被认为是window对象。因此所有全局变量和函数都是作为window对象的属性和方法创建的。代码载入浏览器时,全局执行环境被创建,当我们关闭网页或者浏览器时全局执行环境才被销毁。
2.函数执行环境
每个函数都有自己的执行环境,当执行进入一个函数时,函数的执行环境就会被推入一个执行环境栈的顶部并获取执行权。当这个函数执行完毕,它的执行环境又从这个栈的顶部被删除,并把执行权并还给之前执行环境。这就是ECMAScript程序中的执行流。
2.1定义期
函数定义的时候,都会创建一个[[scope]]属性,通这个对象对应的是一个对象的列表,列表中的对象仅能javascript内部访问,没法通过语法访问。我们定义一全局函数sum,那么sum函数就创建了一个sum的[[scope]]属性。此时,[[scope]]里面只包含了全局对象【Global Object】
简而言之,一个函数的[Scope]属性中对象列表的顺序是上一层函数的Activation Object对象,然后是上上层的,一直到最外层的全局对象。
2.2执行期
当函数被执行的时候,就是进入这个函数的执行环境,首先会创一个它自己的活动对象【Activation Object】(这个对象中包含了this、参数(arguments)、局部变量(包括命名的参数)的定义和一个变量对象的作用域链[[scope chain]],然后,把这个执行环境的[scope]按顺序复制到[[scope chain]]里,最后把这个活动对象推入到[[scope chain]]的顶部。这样[[scope chain]]就是一个有序的栈,这样保了对执行环境有权访问的所有变量和对象的有序访问。
Scope/Scope Chain(作用域/作用域链)
当代码在一个环境中执行时,都会创建一个作用域链。 作用域链的用途是保证对执行环境有权访问的所有变量和函数的有序访问。整个作用域链是由不同执行位置上的变量对象按照规则所构建一个链表。作用域链的最前端,始终是当前正在执行的代码所在环境的变量对象。
如果这个环境是函数,则将其活动对象(activation object)作为变量对象。活动对象在最开始时只包含一个变量,就是函数内部的arguments对象。作用域链中的下一个变量对象来自该函数的包含环境,而再下一个变量对象来自再下一个包含环境。这样,一直延续到全局执行环境,全局执行环境的Variable Object始终是作用域链中的最后一个对象。
内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。
这些环境之间是线性、有次序的。每个环境都可以向上搜索作用域链,以便查询变量和函数名;但任何环境不能通过向下搜索作用域链条而进入另一个执行环境。