5.js引擎执行代码的过程

2020-07-03  本文已影响0人  原来哥哥是万家灯火

先来看看js引擎执行代码的过程:
代码执行分为两个过程,先是分析阶段(可以理解为执行准备阶段),然后是真正执行阶段。分析阶段会对代码进行逐段的分析,在这个过程中完成参数声明、函数提升、变量提升、查明this等工作。执行阶段会对代码进行逐句执行,在这个过程总完成求值、赋值等。分析阶段是逐段,那么什么是段呢?一段全局代码、一个函数、一个eval(),即是一段。比如:

var x = 1;
function f() {}
x = x+1;

上面这段代码就分为两段,整体是一段,然后函数 f 又是一段。

分析阶段的过程:

假设代码段为函数: 
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

执行阶段:

执行阶段会逐句执行代码,求值、完成对参数、变量的赋值等,或进入另一执行环境。如全局代码:

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:

上一篇 下一篇

猜你喜欢

热点阅读