我迷上了V8来源的杂草以及有关该主题的文章,我偶然发现了一篇博客文章,内容是:
如果您被迫用异构元素填充数组,则让 V8通过使用数组常量(尤其是固定大小的数组)早就知道了 小阵列。
let array = [77, 88, 0.5, true]; //V8 knows to not allocate multiple times.
如果是真的,那么为什么是真的?为什么是数组文字?与通过构造函数创建数组相比,有什么特别之处?作为V8源的新手,很难找到同构/异构数组之间的差异所在。
此外,如果回答者可以将我引向相关的V8来源,我们将不胜感激。
编辑:我的问题(数组常量与数组构造函数)稍作澄清
答案 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。