乐趣区

关于javascript:再学JS高级笔记2JavaScript的执行过程

2 JavaScript 的执行过程

如果咱们有上面一段代码,它在 JavaScript 中是如何被执行的 呢?

var name = "why"

function foo(){
    var name = "foo"
    console.log(name)
}

var num1 = 20
var num2 = 30
var result = num1 + num2
console.log(result) 

2.1 第一步:初始化全局对象

JS 引擎会在执行代码之前,在堆内存中创立一个全局对象:Global Object(GO)

  • 该对象所有的作用域 (scope) 都能够拜访
  • 外面会蕴含 DateArrayStringNumbersetTimeoutsetInterval 等等
  • 其中还要一个 window 属性指向本人

    创立 GO 的伪代码

    var GlobalObject = {
        String: '类',
        Date: '类',
        window: GlobalObject,
        name: undefined,
        num1: undefined,
        num2: undefined,
        result: undefined,
        foo: 0xa00// 会指向专门为该函数在内存开拓一个空间地址
    }
  • 开拓的函数空间存储的内容和构造如下:

2.2 第二步:执行调用栈

代码要想运行,都须要先增加到内存外面,内存外面划分为栈构造和堆构造

  1. JS 引擎为了执行代码,外部有一个 执行上下文 (Execution Context Stack, ECS)。那么当初它要执行谁呢?执行的是 全局的代码块(能够了解为函数)。
  2. 为了全局代码也可能失常执行,须要创立 全局执行上下文(Global Execution Context (GEC))
  3. GEC会放入到 ECS 中执行,外面蕴含两局部内容:
  • 第一局部:在代码执行前,在 parser 转成 AST 的过程中,会将全局定义的变量、哈形容等退出到 GlobalObject 中,然而并不会赋值

    • 这个过程也称之为变量的作用域晋升(hoisting)

      var name = "why"
      
      function foo(){
          var name = "foo"
          console.log(name)
      }
      console.log(num1) // 如果在这里退出这行代码,打印的 num1 值为 undefined,因为曾经在 go 外面申明
      var num1 = 20
      var num2 = 30
      var result = num1 + num2
      console.log(result) 
    • 全局执行上下文 GEC 中的 VO(variable Object)就是 GO(Global Object)对象
  • 第二局部:开始执行代码执行,对变量赋值,或者执行其余的函数

2.3 遇到函数如何执行

在执行的过程中执行到一个函数时,就会依据函数体创立一个 函数执行上下文(Functional Execution Context, 简称 FEC),并且压入到 ECStack 中。

FEC 中包含三局部内容:

  • 第一局部:在解析函数成 为 AST 树结构时,会创立一个 Activation Object(AO);

    • AO 中包含形参、arguments、函数定义和指向函数对象、定义的变量
  • 第二局部:作用域链,由 VO(在函数中就是 AO 对象)和父级(parent scope)VO 组成,查找时会一层层查找

    • 当咱们查找一个变量时,实在的查找门路是沿着作用域链来查找的
  • 第三局部:this 绑定的值(this 的绑定规定后续再深究)

2.4 FEC 执行代码

var name = "why"

foo(123)
function foo(num) {console.log(m)
    var m = 10
    var n = 2o
    console.log("foo")
}
  1. 编译阶段:创立全局的 GO,并在 GO 外部定义变量,变量值为undefined
  2. 编译阶段:为 foo 函数开拓内存,并将 GO 内的 foo 指向该地址
  3. 执行阶段:执行var name ="why",为 name 赋值
  4. 执行阶段:执行foo()

    • 为 foo 创立一个 FEC 并放入 ECStask 中
    • 真正开始执行 foo 中的代码
    • 当 foo 执行完后 foo 的 FEC 出栈

2.5 变量环境和记录

后面的解说都是基于晚期 ECMA 的版本标准

在最新的 ECMA 的版本标准中,对一些词汇进行了批改

通过下面的变动咱们能够晓得在最 新的 ECMA 规范中,咱们后面的变量对象 VO 曾经有另一个称说(变量环境,VE)了。

退出移动版