从内存角度理解JS代码执行过程

116 阅读2分钟

下面这段代码是如何执行的呢

var message = "why"
function foo(){
  var message = "foo"
  console.log(message)
}
var num1 = 20
var num2 = 30
var result = num1 + num2
console.log(result)
foo()

全局代码执行之前

  1. JS 引擎在执行代码之前,先在堆内存中创建一个全局对象 GO 。该对象所有的作用域都可以访问。 在浏览器中这个对象就是 window,里面有 Date Array Number setTimeout等等,还会有一个 window 属性指向自己。

image.png

  1. JS 引擎中有一个执行上下文栈,用于执行代码的调用栈,用来执行全局的代码块 image.png
  2. 全局的代码块为了执行,会创建一个全局执行上下文,被放入全局执行上下文栈中 image.png
  3. 在代码执行之前,代码转换 AST 的过程中,会将全局定义的变量、函数加入到全局对象 GO中,这个过程是变量的作用域提升,这些变量提升之后,var定义的变量赋值是undefined,函数赋值地址。 image.png
  4. 每一个执行上下文会关联一个 VO(变量对象) ,变量和函数声明会被添加到这个 VO 对象中,在全局执行上下文 VO = GO,VO是执行上下文中的概念,GO是堆内存中概念。 在下图中,函数对象中的name是foo,外层作用域就是GO了 image.png

全局代码执行之后

  1. 普通变量赋值 image.png
  2. foo函数执行
  • 当执行到函数时,会根据函数体创建一个函数执行上下文(FEC)并被压入到全局执行上下文栈中。
  • 并在堆内存中创建AO对象,每一个执行上下文都有 VO 对象,在函数中 VO=AO

函数执行前:

image.png

函数执行后: image.png