保持对象同态
2024-09-12 本文已影响0人
alue
js 中存在一种优化技巧,就是保持对象同态。名词解释比较费劲,用代码来说明更清楚。如下所示,有三种定义对象的形式。
// setup
let _ = 0
// 1. monomorphic
const o1 = { a: 1, b: _, c: _, d: _, e: _ }
const o2 = { a: 1, b: _, c: _, d: _, e: _ }
const o3 = { a: 1, b: _, c: _, d: _, e: _ }
const o4 = { a: 1, b: _, c: _, d: _, e: _ }
const o5 = { a: 1, b: _, c: _, d: _, e: _ } // all shapes are equal
// 2. polymorphic
const o1 = { a: 1, b: _, c: _, d: _, e: _ }
const o2 = { a: 1, b: _, c: _, d: _, e: _ }
const o3 = { a: 1, b: _, c: _, d: _, e: _ }
const o4 = { a: 1, b: _, c: _, d: _, e: _ }
const o5 = { b: _, a: 1, c: _, d: _, e: _ } // this shape is different
// 3. megamorphic
const o1 = { a: 1, b: _, c: _, d: _, e: _ }
const o2 = { b: _, a: 1, c: _, d: _, e: _ }
const o3 = { b: _, c: _, a: 1, d: _, e: _ }
const o4 = { b: _, c: _, d: _, a: 1, e: _ }
const o5 = { b: _, c: _, d: _, e: _, a: 1 } // all shapes are different
表面上看,三种对象的定义完全等价,只是key的位置有变化而已。但用下面的测试代码可以看出,对象形态略有不同,导致了性能的巨大差异。
// test case
function add(a1, b1) {
return a1.a + a1.b + a1.c + a1.d + a1.e +
b1.a + b1.b + b1.c + b1.d + b1.e }
let result = 0
for (let i = 0; i < 1000000; i++) {
result += add(o1, o2)
result += add(o3, o4)
result += add(o4, o5)
}
单一形态的对象,计算开销要小一个数量级。
原因是js引擎对单一形态的对象,有着更好的优化手段。