优化动态添加的对象属性

JavaScript是最灵活的语言之一,但有时这也会带来性能成本。一个例子就是使用动态添加属性到对象中。奇怪的是,这种性能影响来自于JavaScript引擎为静态类型优化的结果。

V8引擎,用于驱动Chrome和Node.js,使用形状转换链来优化对象属性访问。当两个对象具有相同的属性时,它们被认为具有相同的形状。向对象添加新属性会创建一个转换链来添加新属性。不详细介绍了,很明显,简单的形状比转换链更快。

// 创建一个只有一个属性的对象
const obj = { a: 1 };
// 向对象添加一个新属性
obj.b = 2;
// 访问对象的属性
console.log(obj.a);

回到动态添加属性的问题,引擎无法提前知道将要添加到对象中的属性。因此,它会为每个新属性创建一个转换链。对于少量属性来说,这并不是什么大问题,但是当向对象添加大量属性时,就会成为一个问题。

幸运的是,这很容易解决。最简单的解决方案是提前定义对象的所有可能属性并给它们一个空值(例如nullundefined)。这样,引擎就可以为对象创建一个形状并优化属性访问。虽然这并不总是可能的,但这是一个好的实践。

// 创建一个具有所有可能属性的对象
const obj = { a: 1, b: undefined };
// 向对象添加一个新属性
obj.b = 2;
// 访问对象的属性
console.log(obj.a);