GEC被压入ESC(执行上下文栈)中
在JS引擎内部有一个执行上下文栈(ECS),它刚开始执行的是全局的代码块(GEC),GEC被放入到ECS中执行, 其中GEC被放入到ECS中里面包含两部分内容:
- 第一部分:在代码执行前,
在parser转成AST的过程中,会将全局定义的变量、函数等加入到GlobalObject中,但是并不会赋值(这个过程也被称为变量作用域提升) - 第二部分:在代码指向中,对变量赋值,或者执行其他的函数
其中
函数是以属性的形式先压入到GO中,值为在堆内存中的函数所在地址(在编译到函数时,首先会在堆内存中开辟一个内存保存函数对象,这个对象里记录着该函数的父级作用域以及函数体代码)
GEC开始执行代码
GEC中执行代码时,遇到变量会对变量赋值,如遇到函数(是指调用了函数),就会根据函数体创建一个函数执行上下文(FEC),并且压入到ECS(执行上下文栈)中。 这个FEC中包括三部分内容:
- 第一部分:在解析函数成为AST树结构时,会创建一个AO(Activation Object激活对象):AO中内容与GO中一样,也是包含一些定义的变量,函数定义,以及独属于函数的形参等内容。
- 第二部分:
作用域链:由VO(变量对象,在函数中就是指AO对象)和父级AO对象组成(scope chain: VO + parent scope),查找时会一层层查找(作用域链其实就是这么形成的) - 第三部分:this绑定的值
- 第四部分:就是代码部分了
FEC开始执行代码
FEC执行代码也跟GEC执行代码过程一般无二,也是开始对变量进行赋值,遇到函数调用也是创建一个FEC压入执行上下文栈(ECS)。
版本规范: ES5以前,以及如今最新ECMA版本规范
上述所讲皆是早期ECMA规范(ES5)
每一个执行上下文会被关联到一个变量对象中(VO),在源代码中的变量和函数声明会被作为属性添加到VO中,对于函数来说,参数也会被添加到VO中。
在最新ECMA规范中,对一些词汇有了修改
每一个执行上下文会被关联到一个变量环境中(Variable Enviroment,VE),在执行代码中的变量和函数声明会被作为环境记录添加到VE中,对于函数来说,参数也会被作为环境记录添加到变量环境中。
即在最新规范中,前面所叙VO变为变量环境(VE)了。