我迷失在杂草中的V8来源以及关于这个主题的文章,我发现了一篇博文,其中说:
如果你被迫填充一个包含异构元素的数组,那么让V8早期通过使用数组文字来了解,特别是使用固定大小的小数组.
let array = [77, 88, 0.5, true]; //V8 knows to not allocate multiple times.
Run Code Online (Sandbox Code Playgroud)
如果这是真的,那么为什么会这样呢?为什么是数组文字?对于通过构造函数创建数组而言,有什么特别之处?作为V8源的新手,很难追踪均匀/异构阵列的差异所在.
此外,如果回答者可以指向我相关的V8来源,那将不胜感激.
编辑:我的问题略有说明(数组文字与数组构造函数)
在运行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种不同的元素类型.