V8:异构数组文字

时间:2018-06-20 03:19:36

标签: javascript v8

我迷上了V8来源的杂草以及有关该主题的文章,我偶然发现了一篇博客文章,内容是:

  

如果您被迫用异构元素填充数组,则让   V8通过使用数组常量(尤其是固定大小的数组)早就知道了   小阵列。

let array = [77, 88, 0.5, true]; //V8 knows to not allocate multiple times.

如果是真的,那么为什么是真的?为什么是数组文字?与通过构造函数创建数组相比,有什么特别之处?作为V8源的新手,很难找到同构/异构数组之间的差异所在。

此外,如果回答者可以将我引向相关的V8来源,我们将不胜感激。

编辑:我的问题(数组常量与数组构造函数)稍作澄清

1 个答案:

答案 0 :(得分:5)

blog post提供的Mathias,这是V8开发人员:

常见元素种类

  

在运行JavaScript代码时,V8会跟踪哪种元素   每个数组包含。此信息使V8可以优化任何   专门针对此类元素在数组上执行的操作。对于   例如,当您在数组上调用reduce,map或forEach时,V8可以   根据数组的元素种类优化这些操作   包含。

以该数组为例,

const array = [1, 2, 3];

  

它包含哪些元素?如果您要询问   运算符,它将告诉您数组包含数字。在   语言级别,这就是您所得到的:JavaScript不能区分   在整数,浮点数和双精度数之间-它们都是数字。   但是,在引擎级别,我们可以进行更精确的区分。   该数组的元素类型为PACKED_SMI_ELEMENTS。在V8中,   术语Smi是指用于存储小整数的特定格式。   (我们将在一分钟内进入“包装”部分。)

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

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

....

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

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

关于构造函数与数组文字

如果您不提前知道所有值,请使用数组文字创建一个数组,然后将值推入其中:

const arr = [];
arr.push(10);

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

另外,要弄清孔洞是什么意思,

  

在数组中创建孔(即使数组稀疏)降级   元素对它的“多孔”变体是友好的。 一旦阵列标记为有孔,就永远是有孔的-即使以后打包!

也许值得一提的是V8当前具有21 different element kinds

更多资源