先来看看js引擎执行代码的过程:
代码执行分为两个过程,先是分析阶段(可以理解为执行准备阶段),然后是真正执行阶段。分析阶段会对代码进行逐段的分析,在这个过程中完成参数声明、函数提升、变量提升、查明this等工作。执行阶段会对代码进行逐句执行,在这个过程总完成求值、赋值等。分析阶段是逐段,那么什么是段呢?一段全局代码、一个函数、一个eval(),即是一段。比如:
var x = 1;
function f() {}
x = x+1;
上面这段代码就分为两段,整体是一段,然后函数 f 又是一段。
分析阶段的过程:
-
创建一个对象,用于保存这段代码的环境信息,这个对象叫做执行期上下文对象。
let context = { [[scope]], VO, this };
执行期上下文有三个属性,[[scope]]是作用域链,VO是变量对象,this就是当前this指向。 -
将执行期上下文压入执行期上下文栈,(简称执行栈)。
let stack = [];
stack.push(context); -
依次解析此段代码的形式参数、声明函数、声明变量,然后保存在变量对象VO上
解析形式参数(这一步只有函数上下文才有):
在变量对象上的一个属性,属性名是形参名,值是 undefined
假设代码段为函数:
function f(phoneNumber) {}
context.VO = {
arguments: {
0: undefined
},
phoneNumber: undefined
}
声明函数(这就是函数提升):
在变量对象上的一个属性,属性名是函数名,值是函数的引用。
context.VO = {
f: reference to function f(){}
}
如果变量对象已经存在相同名称的属性,则完全替换这个属性。如:
function f (a) {
function a() {};
console.log(a);
}
打印结果是个函数。
同理,两个同名函数,第一个会被第二个覆盖掉。
function f (a) {}
function f (a) {}
context.VO = {
f: reference to the 2nd function f(){}
}
试运行一段代码:
function fn() {
console.log(1)
}
fn();
function fn() {
console.log(2)
}
打印结果是2
声明变量(这就是变量提升):
在变量对象上的一个属性,属性名是变量名,值是 undefined。
context.VO = {
phoneNumber: undefined
}
如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性。
var c = 1;
var c;
console.log(c);
打印结果是1
var x = 1;
function x() {};
console.log(x);
打印结果还是1
- 查明this指向
执行阶段:
执行阶段会逐句执行代码,求值、完成对参数、变量的赋值等,或进入另一执行环境。如全局代码:
var x = 1;
function f() {
var y = 2;
console.log(x)
}
f();
分析阶段完成后,其变量对象是这样的:
globalContext.VO = {
x: undefined,
f: reference to function f(){}
}
执行x = 1;
globalContext.VO = {
x: 1,
f: reference to function f(){}
}
执行f()
创建 f 的执行期上下文,f 的上下文入栈...
stack = [globalContext, fContext]...
with语句、try...catch语句的catch,都会改变作用域链。with会把参数添加到作用域链的最前端,catch会把错误信息添加到作用域链的最前端。
栈是一种数据结构,其特点是先入后出,后入先出。比如一个数组,let arr = [],当放入和移出数据,只使用push和pop,或者只使用unshift和shift时,它就具有先入后出、后入先出的特点,这就实现了一个栈。
变量对象VO是一个抽象概念,是语言规范内规定的抽象概念。全局上下文的变量对象是全局对象,函数上下文变量对象是活动对象。globalContext.VO 是global object,fnContext.VO是fnContext.AO
Variable object is an abstrat thing,which can be either of those:
- global object (in global context)
- activation object (in funtion context)
网友评论