Javascript v8 引擎和 Web API

fso*_*ety 6 javascript google-chrome v8 node.js

我一直在阅读 Javascript 的内部结构(在 chrome 浏览器的上下文中),我有几个问题似乎找不到正确的答案。

按照我的理解:

  • 核心 Javascript(根据 ECMA 规范)包含在 V8 引擎中。

  • 类似settimeout的功能由浏览器的 Web API 提供。

  • V8 引擎包括一个调用栈,任何要执行的 Javascript 都会被推送到这个栈上。

  • 然后通过 Web API 调用非标准函数。

  • 这些在完成时被推送到回调队列。

  • 一旦堆栈为空,回调队列中的任何内容都会被事件循环推入堆栈。

我的问题是当 V8 引擎解释 Javascript 代码时,它如何知道特定功能来自 Web API?Web API 是如何与引擎实际链接的?

jfr*_*d00 5

类似setTimeout()的API被添加到globalJavascript 中的对象中。当 JS 引擎要解析一个符号时,它会从本地范围开始并向上延伸到一系列范围。链的最末端是global范围。

作为初始化 V8 引擎的一部分,宿主环境可以将它自己的 API 添加到 V8 引擎的全局范围内,这正是浏览器为 V8 中尚未内置的东西所做的事情。

浏览器中全局对象的概念比它应该的要混乱一些。多年来,全局对象就是window对象。所有全局可访问的宿主环境函数,如对象的setTimeout()属性window

类似地,在浏览器的顶级范围内声明任何变量都会自动使这些变量成为window对象的属性。

这很快就变得一团糟。当 newclass关键字出现时,他们决定不再让这种混乱变得更糟,因此在浏览器顶级范围内声明的类在全局范围内可用,但不会作为window对象的属性添加。

当 node.js 环境出现时,他们将用户代码组织成模块,目标是尽可能少地使用全局变量。在该环境中,全局变量是名为global. 您在 node.js 模块中的顶层声明的变量的范围仅限于模块内。没有任何东西会自动成为全局变量,但是global如果您愿意,您可以显式地为对象分配一个新属性,例如:

global.myProperty = 3;
Run Code Online (Sandbox Code Playgroud)

尽管在 node.js 模块化设计中强烈不鼓励这样做。

因此,在初始化 V8 引擎时,浏览器环境将 ECMAScript 规范之外的任何 APIsetTimeout()添加到浏览器中 Javascript 的顶层,例如添加到global对象中。