使用 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   

我們可以看到,兩者之間的效能改進非常不同。