【问题标题】:The Javascript v8 engine and Web APIsJavascript v8 引擎和 Web API
【发布时间】:2020-04-06 13:49:40
【问题描述】:

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

据我了解:

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

  • settimeout 等函数由浏览器的 Web API 提供。

  • V8 引擎包括一个调用堆栈和任何要被 执行被推到这个堆栈上。

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

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

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

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

【问题讨论】:

标签: javascript node.js google-chrome v8


【解决方案1】:

setTimeout() 等 API 被添加到 Javascript 中的 global 对象中。当 JS 引擎想要解析一个符号时,它从本地范围开始,然后沿着范围链上升。在链的最末端是global 范围。

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

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

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

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

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

global.myProperty = 3;

尽管这在 node.js 模块化设计中是非常不鼓励的。

因此,在浏览器中的 JavaScript 顶层添加的任何 ECMAScript 规范之外的 API(如 setTimeout())都会在初始化 V8 引擎时由浏览器环境添加到 global 对象中。

【讨论】:

  • 那么V8中定义了全局对象,一旦浏览器加载,这些Web API函数就会被浏览器添加到全局对象中?
  • @fsociety - 作为初始化 Javascript 环境的一部分,宿主环境可以在该 Javascript 环境中创建对象(超出 ECMAScript 本身的一部分),以使它们可用于在该环境中运行的任何脚本。
  • @fsociety - 我在答案中添加了更多内容。
  • 我明白了。那么一旦函数在全局对象中,并准备好执行,V8 引擎会将其视为任何其他函数并将其推送到调用堆栈上?而且我假设一旦在堆栈上处理了这个函数,就会执行任何定义;在setTimeout 的情况下,哪个将链接到对全局范围之外的某些低级实现的进一步函数调用(?)。
  • @fsociety - 就 JS 引擎而言,它只是任何其他功能。当您调用它时,它将被压入调用堆栈并执行其代码。该函数背后的代码可能全部是 Javascript,也可能绑定到本机代码(V8 有一个开发人员 API,用于将本机代码绑定到 JS 函数)。 setTimeout() 确实绑定到一些本机代码来管理和触发计时器。
猜你喜欢
  • 2011-09-22
  • 1970-01-01
  • 2013-04-21
  • 2013-01-02
  • 2014-05-11
  • 2015-05-16
  • 1970-01-01
  • 2011-05-27
  • 1970-01-01
相关资源
最近更新 更多