使用 null 初始化对象属性
所有现代 JavaScript JIT 编译器都试图根据预期的对象结构优化代码。一些小费从 MDN 。
幸运的是,对象和属性通常是可预测的,在这种情况下,它们的底层结构也是可预测的。JIT 可以依靠它来更快地进行可预测的访问。
使对象可预测的最佳方法是在构造函数中定义整个结构。因此,如果你要在创建对象后添加一些额外的属性,请使用 null
在构造函数中定义它们。这将有助于优化器预测其整个生命周期中的对象行为。但是,所有编译器都有不同的优化器,并且性能提升可能不同,但总体而言,最好在构造函数中定义所有属性,即使它们的值尚未知晓。
一些测试的时间。在我的测试中,我正在创建一个带有 for 循环的一些类实例的大数组。在循环中,我在数组初始化之前为所有对象的 x
属性分配相同的字符串。如果构造函数使用 null 初始化 x
属性,则数组总是处理得更好,即使它正在执行额外的语句。
这是代码:
function f1() {
var P = function () {
this.value = 1
};
var big_array = new Array(10000000).fill(1).map((x, index)=> {
p = new P();
if (index > 5000000) {
p.x = "some_string";
}
return p;
});
big_array.reduce((sum, p)=> sum + p.value, 0);
}
function f2() {
var P = function () {
this.value = 1;
this.x = null;
};
var big_array = new Array(10000000).fill(1).map((x, index)=> {
p = new P();
if (index > 5000000) {
p.x = "some_string";
}
return p;
});
big_array.reduce((sum, p)=> sum + p.value, 0);
}
(function perform(){
var start = performance.now();
f1();
var duration = performance.now() - start;
console.log('duration of f1 ' + duration);
start = performance.now();
f2();
duration = performance.now() - start;
console.log('duration of f2 ' + duration);
})()
这是 Chrome 和 Firefox 的结果。
FireFox Chrome
--------------------------
f1 6,400 11,400
f2 1,700 9,600
我们可以看到,两者之间的性能改进非常不同。