如何提升擴展運算符的性能

博客地址:https://github.com/Wscats/articles/issues/88git

在這篇文章中,咱們會進行一個有趣的測試,看看咱們如何提升擴展運算符的性能。github

讓咱們首先簡要介紹一下擴展運算符在數組中的工做原理。數組

擴展運算符,也就是咱們經常使用的三個,讓數組展開變成每一個小塊。 而後使用中括號語法[],從新組裝這些小塊構造一個新數組。瀏覽器

擴展運算符能夠被放置在中括號[]裏面的任何位置。性能優化

const numbers = [1, 2, 3];
[0, ...numbers];    // => [0, 1, 2, 3]
[0, ...numbers, 4]; // => [0, 1, 2, 3, 4]
[...numbers, 4];    // => [1, 2, 3, 4]

回答咱們一開始提出的問題,擴展運算符在數組文字中的位置是否能夠提升性能?讓咱們日後繼續探究。數據結構

附加到頭部和尾部功能

在開始性能比較以前,讓咱們定義兩個函數。app

第一個是appendToTail()函數

function appendToTail(item, array) {
  return [...array, item];
}

const numbers = [1, 2, 3];
appendToTail(10, numbers); // => [1, 2, 3, 10]

appendToTail()可讓你在數組的末尾插入一個值。 此函數使用瞭如下寫法[...array, item]性能

第二個是appendToHead()測試

function appendToHead(item, array) {
  return [item, ...array];
}

const numbers = [1, 2, 3];
appendToHead(10, numbers); // => [10, 1, 2, 3]

appendToHead()是一個純函數,它返回一個新數組,其中添加的值是插入在原數組的頭部。它使用[item, ...array]

講道理就上面這兩個函數的表現,沒有理由認爲這些功能會有不同的效率。可是事實可能跟咱們想象中不同,下面讓咱們來繼續測試吧。

性能測試

我用MacBook Pro在如下3個瀏覽器的筆記本電腦上測試[... array, item][item, ...array],對比二者的性能:

  • Chrome 76
  • Firefox 68
  • Safari 12.1

如下是性能測試結果:

屏幕快照 2019-09-06 上午11 28 09

正如預期的那樣,在Firefox和Safari瀏覽器中[...array, item][item, ...array]具備相同的性能。

可是,在Chrome中,[...array, item]的執行速度比[item, ...array]快兩倍。 這是一個有用的結果。

要在Chrome中提升擴展運算符的性能,請在數組文字的開頭使用擴展運算符:

const result = [...array, item];

但另外一個問題出現了:這種問題怎麼引發的?

從V8引擎的7.2版本以後,爲Chrome中的JavaScript執行提供支持,能夠對擴展運算符進行新的優化:快速路徑優化

用幾句話描述它的工做原理,以下:

若是沒有這個優化,當引擎遇到擴展運算符[...iterable, item]時,它會調用可迭代對象的迭代器iterator.next()。在每次迭代時,結果數組的內存都會增長,迭代結果會被添加到結果數組中。

可是快速路徑優化檢測到已知的可迭代(如整數數組)並徹底跳過迭代器對象的建立。 而後引擎讀取擴展數組的長度,僅爲結果數組分配一次內存。 而後經過索引傳播數組,將每一個項目添加到結果數組中。

快速路徑優化會跳過迭代對象的建立,只爲結果分配一次內存。 從而性能提升。

支持的數據結構

快速路徑優化適用於如下標準JavaScript數據結構。

數組

const numbers = [1, 2, 3, 4];

[...numbers, 5]; // => [1, 2, 3, 4, 5]

字符串

const message = 'Hi';

[...message, '!']; // => ['H', 'i', '!']

Sets

const colors = new Set(['blue', 'white']);

[...colors, 'green'];          // => ['blue', 'white', 'green']
[...colors.values(), 'green']; // => ['blue', 'white', 'green']
[...colors.keys(), 'green'];   // => ['blue', 'white', 'green']

Maps

在Map對象中,僅支持map.keys()map.values()方法:

const names = new Map([[5, 'five'], [7, 'seven']]);

[...names.values(), 'ten']; // => ['five', 'seven', 'ten']
[...names.keys(), 10];      // => [5, 7, 10]

結論

當被擴展的數組位於數組的開頭時,因爲快速路徑優化,您能夠得到性能提高。它適用於V8引擎7.2版本(Chrome v72和NodeJS v12附帶的特性)。

經過此優化,性能測試顯示[... array, item]的執行速度至少比[item, ...array]快兩倍。

請注意,雖然快速路徑確實頗有用,建議您在性能很重要或者處理大型數組的地方使用它。

由於,在大多數狀況下,強制優化,最終用戶極可能不會感受到任何差別。

您還知道JavaScript中有哪些有趣的性能優化,能夠在下面評論中告訴我?

若是文章能帶您一絲幫助或者啓發,請不要吝嗇你的贊和Star,對我是前進的動力和最大的確定😁

相關文章
相關標籤/搜索