JS执行流程

47 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

JS执行流程

1.执行前

  1. 对源代码进行词法分析、语法分析, 创建执行栈(ECS, Excution Context Stack),与一个堆空间

  2. 创建一个全局执行上下文(GEC,Golbal Excution Context)

  3. 在堆空间创建一个GO(Golbal Object),如果运行环境是浏览器这个GO就是window,那么就会创建一些全局属性如Date,Math,String,Number等,且还有一些代码中声明的全局作用域下的变量与函数并初始化。例如

  4. var message = '123'
    function foo(num) {
      var name = 'zhangsan'var age = 18
      var doubleNum = num * 2
    }
    foo(2)
    
  5. 变量的message初始值为undefined

  6. 函数较为特殊, 解析到函数foo时则会创建一个函数对象,这个函数对象会初始化一些函数的属性(如length, name, arguments,[[ Scope]] 以及 函数代码 等),并这个对象的地址值赋给GO的foo属性(注意函数的作用域 [[ scope ]] 已经确定且为GO

  7. 创建一个EC并将其压栈(ECS)。这个EC为GEC,因为每创建一个EC就会关联一个VO(Variable Object), this, Scope Chain,此时GEC的VO会指向GO, this为undefined, Scope Chain为GO

2. 开始代码

  1. (步骤1.7)GEC中的this赋值为window
  2. message赋值操作, GO中的message属性变为'123'
  3. 执行foo函数之前
    1. 在堆空间创建一个AO(Active Object),AO中进行初始化,函数体中声明的变量为undefined, 函数体中声明的函数则会被赋值新函数对象的地址值(重复1.3-1.4的操作)作为AO的属性。例子中,会创建属性num, name, age, doubleNum,值为undefined
    2. 创建一个EC并将其压栈(ECS)。这个EC为FEC(Function Excution Context),这FEC会关联一个VO,而此时的VO就是步骤2.3中创建的AO。此时的this为undefined,Scope Chain为AO + [[ Scope ]],(这个[[ Scope ]]就是步骤1.6中那个[[ Scope ]])
  4. 开始执行函数
    1. FEC中的this赋值, 根据调用方式来判断。此例子中属于时独立调用,this会被隐式绑定为GO
    2. num赋值
    3. name赋值
    4. age赋值
    5. doubleNum赋值
  5. 函数执行完成
    1. FEC被弹出ECS
    2. (可能会出现的步骤)AO对象被垃圾回收(GC, Garbage Collection)

3. 所有代码执行完成

  1. GEC被弹出ECS
  2. 堆空间中的所有对象被垃圾回收

这是我的个人博客,欢迎点击!!