天天看點

JS中,如何提高展開運算符的性能

為了保證的可讀性,本文采用意譯而非直譯。

本文主要講解怎麼提高展開運算的性能,在此之前先簡單說說展開運算在數組中的工作原理。

展開運算符或三個點,接受一個數組數組或通常是可疊代的[... arrayOrIterable]并将數組元素分解,并使用這些分解部分構造一個新數組。

展開運算符可以放在數組中的任何位置:

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]複制代碼      

現在有一個有趣的問題,展開運算符在數組中的位置是否可以提高性能?讓咱們來look look。

1. 附加到頭部和尾部函數

在開始對比性能之前,先定義兩個函數。

第一個函數:appendToTail():

function appendToTail(item, array) { return [...array, item];
}const numbers = [1, 2, 3];
appendToTail(10, numbers); // => [1, 2, 3, 10]複制代碼      

appendToTail()函數功能主要是将 item插入數組的末尾。

第二個函數 appendToHead():

function appendToHead(item, array) { return [item, ...array];
}const numbers = [1, 2, 3];
appendToHead(10, numbers); // => [10, 1, 2, 3]複制代碼      

appendToHead() 是一個純函數,它傳回一個新數組,通過[item,... array]騷操作将 item 放到所傳入數組的後面。

乍一看,沒有理由認為這些函數的性能會不同,但是,事實勝于熊辯,來 look look.

2. 性能測試

在MacBook Pro筆記本電腦上用以下3個浏覽器的運作[... array,item] 和 [item,... array],來看看對應的性能:

  • Chrome 76
  • Firefox 68
  • Safari 12.1

測試結果:

JS中,如何提高展開運算符的性能

如上面所看到,在Firefox和Safari浏覽器中[... array,item]和[item,... array]的性能基本一樣。

但是,在Chrome中,[... array,item]的執行速度比[item,... array]快兩倍。這個結果對咱們來說很有用。

要在Chrome中提高展開運算符的性能,隻需要将展開操作放到數組的開頭就哦了。

const result = [...array, item];
複制代碼      

但這又是為啥,為什麼會發生這種情況?

3.快速路徑優化( fast-path optimization)

啟動V8引擎的 7.2版本(為Chrome中的JS執行提供支援),可以對展開運算符進行新的優化:快速路徑優化。

簡單說,它的工作原理如下:

如果沒有這種優化,當引擎遇到一個展開操作符[...iterable, item],它調用iterable對象的iterator (iterator.next())方法。在每次疊代中,最後傳回的數組的記憶體都會增加,并将疊代結果添加到其中。

但是快速路徑優化檢測到一個已知的可疊代對象(就像一個整數數組),并完全跳過iterator對象的建立。然後,引擎讀取擴充數組的長度,隻為結果數組配置設定一次記憶體。然後傳遞展開數組的索引,将每個元素添加到結果數組中。

快速路徑優化會跳過疊代對象的建立,隻為結果配置設定一次記憶體,進而性能提高。

4.支援資料結構

快速路徑優化适用于以下标準JS資料結構。

array

const numbers = [1, 2, 3, 4];
[...numbers, 5]; // => [1, 2, 3, 4, 5]複制代碼      

string

const message = 'Hi';
[...message, '!']; // => ['H', 'i', '!']
複制代碼      

set

const colors = new Set(['blue', 'white']);
[...colors, 'green']; // => ['blue', 'white', 'green']
[...colors.values(), 'green']; // => ['blue', 'white', 'green']
[...colors.keys(), 'green']; // => ['blue', 'white', 'green']
複制代碼      

map

關于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引擎v7.2中可用(在Chrome v72和NodeJS v12中提供)。

通過快速路徑優化,[... array,item]的執行速度至少比[item,... array]快兩倍。

請注意,雖然f快速路徑優化确實很有用,但是在大多數情況下,可以不用強制進行優化,因為最終使用者很可能不會感覺到差别,當然,如果咱們在處理大型數組,就可能些優化方案。

js