Javascript引擎、执行上下文和调用栈

概览

本文旨在记录自己学习V8引擎、执行上下文和调用堆栈是什么,以及他们之间的关系,通过阅读本文,你将会了解JavaScript是如何运行的,在项目中也会编写更好的程序。如有错误请在评论中指出。

V8

由 Google 构建的 V8 引擎是开源的,用 C ++ 编写。 此引擎被用在 Google Chrome 中。 与其他引擎不同的是,V8 也被用于流行的 Node.js 中。

V8引擎是一个比较流行的JavaScript解释器,它主要包含两个重要的组件:

  • Memory Heap (内存堆),内存分配的地方
  • Call Stack (调用堆栈),码执行时栈帧存放的位置

V8

执行上下文(Execution Context)

引擎在加载完代码后会解析代码,创建一个执行环境,形成一个作用域,这个执行环境便是执行上下文。
执行上下文分为3中:

  • 全局执行上下文(全局作用域)
  • 函数内部执行上下文(局部作用域)
  • eval,不推荐使用

call stack(调用堆栈)

在当前执行环境中遇到函数时,会将函数压入一个栈(一种数据结构)中并执行函数,若函数中还有函数调用,会继续将遇到的函数压入栈中并执行,函数执行完后会将其弹出栈

图解三者关系

本文只介绍引擎、执行上下文、调用堆栈之间的关系,关于Event Loop会在后续文章中介绍

如上图所展示一样:

  1. 引擎在加载完代码后,创建全局执行上下文
  2. 解析代码,在代码中找到函数申明和变量定义语句,将变量和函数存储在堆内存中
  3. 执行代码,如果遇到函数将其压入call stack中并执行函数first()
  4. 每当函数执行时,又会创建一个局部执行上下文(局部作用域)
  5. 如果再次遇到函数,重复2-4步骤
  6. 函数执行完后,此函数将被从调用栈中弹出

代码示例

1
2
3
4
5
6
7
8
9
10
console.log(a)

function say() {
console.log('say')
}

var a = 'aa';
var b = 'bb';

say()
  • js引擎加载完这段代码,创建一个全局执行上下文
  • 解析代码,找到定义的变量和申明的函数,将其存入堆内存中
    1
    2
    3
    4
    5
    // Memory Heap

    a: undefined
    b: undefined
    say: function() {}
  • 执行代码,首先将console.log(a)压入栈中并执行,结果为undefined

  • 执行完后将其弹出栈

  • 函数say引用和变量a,b赋值

    1
    2
    3
    4
    5
    // Memory Heap

    a: 'aa'
    b: 'bb'
    say: function() {console.log('say')}
  • say()压入call stack中并执行,这个过程中又会创建一个局部作用域

  • 执行say()中的代码时遇到console.log('say'),将其压入call stack中

  • 执行完console.log('say')将其弹出栈,继续执行say()中剩余的代码

  • 执行完say()将其弹出栈,继续执行全局执行上下文中剩余的代码,直至执行完

  • 关闭浏览器,销毁全局执行上下文

本文结束,希望内容对正在浏览的你有所帮助,如有错误,希望指出。

参考文章: