美文网首页
5.js引擎执行代码的过程

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

作者: 原来哥哥是万家灯火 | 来源:发表于2020-07-03 12:50 被阅读0次

先来看看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)

相关文章

网友评论

      本文标题:5.js引擎执行代码的过程

      本文链接:https://www.haomeiwen.com/subject/pohsqktx.html