JavaScript V8引擎和Web API

8

我一直在阅读Javascript的内部机制(以Chrome浏览器为例),有几个问题我找不到合适的答案。

据我理解:

  • ECMA规范中的核心Javascript被包含在V8引擎中。

  • settimeout这样的函数是由浏览器的Web API提供的。

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

  • 非标准函数通过Web API进行调用。

  • 这些函数完成后,将被推送到回调队列中。

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

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


2
一个帖子里包含多个问题还是多个帖子? - adiga
1
这是一个非常大的问题。考虑将其拆分成小问题? - evolutionxbox
1个回答

7

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模块化设计中是强烈不推荐的。

因此,任何在浏览器中作为顶层添加的,超出ECMAScript规范的API,如setTimeout(),会在浏览器环境初始化V8引擎时被添加到global对象中。


那么全局对象是在V8中定义的,一旦浏览器加载,这些Web API函数就会被浏览器添加到全局对象中? - Priyath Gregory
1
@fsociety - 作为初始化Javascript环境的一部分,宿主环境可以在该Javascript环境中创建对象(超出ECMAScript本身的范围),以使它们可用于在该环境中运行的任何脚本。 - jfriend00
@fsociety - 我在我的回答中添加了更多内容。 - jfriend00
我明白了。所以一旦函数在全局对象中并准备好执行,V8引擎将像处理其他函数一样将其推送到调用堆栈上? 我猜一旦该函数在堆栈上被处理,任何定义都将被执行; 在setTimeout的情况下,这将链接到一些低级实现的进一步函数调用,超出全局范围(?)。 - Priyath Gregory
1
@fsociety - 就JS引擎而言,它只是另一个函数。当您调用它时,它将被推送到调用堆栈中,并且其代码将执行。该函数背后的代码可以是全部JavaScript,也可以绑定到本地代码(V8具有将本地代码绑定到JS函数的开发人员API)。setTimeout()确实绑定了一些本地代码来管理和触发计时器。 - jfriend00

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接