我刚刚读到有关隐藏类和内联缓存的内容。我发现了有趣的表演,这让我心碎。
所以,我们有以下代码:
const n = 100000;
const array = [];
for (let i = 0; i < n; i++) {
array.push({ a: '2', b: '3', c: '4', d: '5' });
}
const date1 = Date.now();
const array1 = array.map(i => ({ someNewField1: 'test1', someNewField2: 'test2', ...i }))
console.log('first map: ', Date.now() - date1);
const date2 = Date.now();
const array2 = array.map(i => ({ ...i, someNewField: 'test1', someNewField2: 'test2', }))
console.log('second map:', Date.now() - date2);
如果您在计算机上运行此程序,您会发现第一个地图循环的运行速度比第二个快 5 倍。
我在 Chrome 控制台中运行了这段代码并获得了内存快照。正如我所看到的,在第一种情况下,我得到了新的数组(array1),其中所有对象都具有相同的隐藏类(映射)。所以这个 array.map 循环运行得很快。但在第二种情况下,我得到了新数组(array2),其中只有 9 个第一个元素具有相同的隐藏类,该隐藏类具有从原始数组(数组)元素指向隐藏类的反向指针。但第二个数组(array2)中的其他元素具有独特的隐藏类,它们没有任何后向指针。我还注意到从 array2 访问对象字段很慢。
所以我认为,在前 9 个元素之后,V8 引擎开始创建慢属性对象,但为什么?
看起来像是多种优化相互干扰的情况,导致最终结果的优化程度低于应有的程度。报告于 crbug.com/v8/13303。
2023 年更新:此问题已在 Chrome 117 中修复。