V8:异构数组文字

Mat*_*att 9 javascript v8

我迷失在杂草中的V8来源以及关于这个主题的文章,我发现了一篇博文,其中说:

如果你被迫填充一个包含异构元素的数组,那么让V8早期通过使用数组文字来了解,特别是使用固定大小的小数组.

let array = [77, 88, 0.5, true]; //V8 knows to not allocate multiple times.
Run Code Online (Sandbox Code Playgroud)

如果这是真的,那么为什么会这样呢?为什么是数组文字?对于通过构造函数创建数组而言,有什么特别之处?作为V8源的新手,很难追踪均匀/异构阵列的差异所在.

此外,如果回答者可以指向我相关的V8来源,那将不胜感激.

编辑:我的问题略有说明(数组文字与数组构造函数)

Der*_*ard 5

来自这位由V8开发人员Mathias提供的博文:

常见元素种类

在运行JavaScript代码时,V8会跟踪每个数组包含的元素类型.此信息允许V8针对此类元素优化阵列上的任何操作.例如,当您在数组上调用reduce,map或forEach时,V8可以根据数组包含的元素类型优化这些操作.

拿这个数组,例如:

const array = [1, 2, 3];

它包含哪些元素?如果您询问typeof运算符,它会告诉您数组包含数字.在语言层面,这就是你得到的:JavaScript不区分整数,浮点数和双精度数 - 它们都只是数字.但是,在引擎级别,我们可以做出更精确的区分.此数组的元素类型为PACKED_SMI_ELEMENTS.在V8中,术语Smi指的是用于存储小整数的特定格式.(我们将在一分钟内到达PACKED部分.)

稍后将浮点数添加到同一个数组会将其转换为更通用的元素类:

const array = [1, 2, 3];
// elements kind: PACKED_SMI_ELEMENTS
array.push(4.56);
// elements kind: PACKED_DOUBLE_ELEMENTS
Adding a string literal to the array changes its elements kind once again.

const array = [1, 2, 3];
// elements kind: PACKED_SMI_ELEMENTS
array.push(4.56);
// elements kind: PACKED_DOUBLE_ELEMENTS
array.push('x');
// elements kind: PACKED_ELEMENTS
Run Code Online (Sandbox Code Playgroud)

....

V8为每个阵列分配一种元素类型.数组的元素不是一成不变的 - 它可以在运行时更改.在前面的示例中,我们从PACKED_SMI_ELEMENTS转换为PACKED_ELEMENTS.元素种类转换只能从特定种类转变为更一般的种类.

因此,在幕后,如果您在运行时不断向阵列添加不同类型的数据,V8引擎必须在幕后进行调整,失去默认优化.

至于构造函数与数组文字

如果您未提前知道所有值,请使用数组文字创建一个数组,然后将值推送到它:

const arr = [];
arr.push(10);
Run Code Online (Sandbox Code Playgroud)

这种方法可确保数组永远不会转换为多孔元素.因此,V8可以更有效地优化阵列上的任何未来操作.

另外,澄清多孔的意思,

在数组中创建孔(即使数组稀疏)将元素类降级为其"多孔"变体.一旦阵列被标记为多孔,它永远是空洞的 - 即使它后来被打包!

值得一提的是,V8目前有21种不同的元素类型.

更多资源

  • 好东西.我仍然迷失在consructor vs literal上.假设我做`const c = new Array(true,1,2,'cat')`然后执行`const d = [true,1,2,'cat']`.V8会不同地看到这些?如果两者之间甚至存在差异,那么似乎有些含糊不清(参见[此较旧的SO帖子](/sf/ask/65231071/和而-声明-A-的JavaScript-AR)).谢谢! (2认同)
  • @Matt在那个特定的例子中,确实没有那么大的区别,主要是因为你在两个实例中都开始使用具有值的数组.`[]`优先于构造函数的主要位置是这种类型的例子:`const array = new Array(3);` (2认同)
  • 因为有效的是,你是直接从跳跃创建一个多孔类型的数组 (2认同)