JavaScript 如何工作

79 阅读3分钟

核心组件

  • JavaScript 引擎
  • JavaScript 运行时环境
  • 调用堆栈
  • 并发和事件循环

下面将简单展开讨论下。

JavaScript 引擎

JavaScript 是一种解释型编程语言,不会在源代码执行之前被编译为二进制代码,而我们的计算机是无法直接理解纯文本脚本的,因此需要有一种程序能够先解释 JavaScript 代码,这就是 JavaScript 引擎的工作。

目前所有浏览器都内置了 JavaScript 引擎,浏览器加载 JavaScript 文件到内存中后, JavaScript 引擎会逐行(不同引擎有不同解译优化方式)解译代码,将其转换为机器码,然后由计算机底层去执行。

image.png

引擎种类

1.V8

这是由 Google 开发的开源 JavaScript 引擎,用于 Google Chrome 和 Chromium 中,以 V8 发动机命名。在执行之前将 JavaScript 编译为机器代码,而非字节码或者解释执行,使用了内联缓存等方法提高性能。

2.Spider monkey

第一款 JavaScript 引擎,早期用于 Netscape Navigator ,现在用于 Mozilla Firefox。

3.JavaScriptCore

开放源代码,用于 Safari。

4.Chakra

JScript 引擎,用于 Internet Explorer。 JavaScript 引擎,用于 Microsoft Edge。

引擎主要由两个组件组成:

  • 内存堆(Memory Heap),是一个非结构化的内存池,用于内存分配,存储应用程序的所有对象。
  • 调用堆栈(Call Stack),代码执行时堆栈帧所在的位置,代码实际执行的地方。

JavaScript 运行时环境

有了 JavaScript 引擎后就有了基础,但是引擎也不是孤立运行的,我们还需要 JavaScript 运行时环境,它由许多组件构成。

1.JavaScript 引擎

2.网络 API

3.回调队列或消息队列

4.事件表

5.事件循环

调用堆栈

由于 JavaScript 一般来说是单线程的,意味着一次只能做一件事,而执行代码时就用到了一个调用堆栈。

当我们执行进入一个函数的时候,引擎会将它放在栈顶,从一个函数返回离开的时候,引擎会将它从栈顶弹出。调用堆栈中的每个条目称为堆栈帧。

并发和事件循环

如果只是单纯的在调用堆栈中入栈和出栈,一个很明显的问题就是会造成浏览器UI操作的阻塞,遇到重型任务执行时会在很长一段时间内停止响应,甚至会引发浏览器的错误告警。

为了并发处理事件, JavaScript 程序输入/输出使用事件和回调函数执行,这样就能在处理大型任务时还能够处理鼠标单击等任务。 ES6 还引入了 Promise 用于优雅的处理异步事件,可以使传统的基于回调的异步代码更加清晰和简单。

比如在 Node.js 中,它将 I/O 操作移交给 OS 内核,并将 I/O 操作的回调推迟到以后。这允许 Node.js 在 I/O 操作移交给 OS 后立即处理其它任务,而无需等到 OS 完成 I/O 任务。

image.png