如何更高效的拼接字串?

Thoughtful valiant.發表於2018-12-08

最常用的連線字串的方法應該是下面幾種:

// 1.=操作符
str = 'a' + 'b' + 'c';
// 2. +=操作符
str = 'a';
str += 'b';
str += 'c';
// 3. Array.join()
str = ['a', 'b', 'c'].join('');
// 4. String.concat()
str = 'a';
str = str.concat('b', 'c');
複製程式碼

那麼來看一下這幾種有什麼區別,或者會造成什麼影響。


= 和 +=操作符

執行str += 'one' + 'two'會經歷以下4個過程:

  1. 在記憶體中建立一個臨時字串;
  2. 連線後的字串onetwo被賦值給該臨時字串;
  3. 臨時字串與str當前的值連線;
  4. 結果賦值給str

拼接這個短短的字串就會經歷以上4個步驟,那麼可以進行優化嗎?請看下面的程式碼:

// 1
str += 'one';
str += 'two';
// 2
str = str + 'one' + 'two';
複製程式碼

以上兩種方式雖然能達到同樣的效果,但是卻可以避免產生臨時字串(也就是4個步驟中的1&2步驟);在大多數瀏覽器中這樣做會提速10%~40%(IE7以上,IE8效果不明顯,實現機制與此不同)。

但是如果將上面的程式碼2換成:str = 'one' + str + 'two',則優化將失效。這與瀏覽器合併字串時分配記憶體的方法有關:

除IE外,其他瀏覽器會嘗試為表示式左側的字串分配更多的記憶體,然後簡單地將第二個字串拷貝至它的末尾。如果在一個迴圈中,基礎字串位於最左端的位置,就可以避免重複拷貝一個逐漸變大的基礎字串。

基本字串可以理解為連線時排在前面的字串。也就是說:str + 'one'意味著拷貝one並附加在str之後,而'one' + str則意味著要拷貝str並附加在'one'之後,如果str很大,拷貝過程的效能損耗(記憶體佔用)就會很高。

說回IE8的實現機制:

在IE8的實現中,連線字串只是記錄現有的字串的引用來構造新的字串。在最後時刻(當你真正要使用連線後的字串時),字串的各個部分才會逐個拷貝到一個新的“真正的”字串中,然後用它取代先前的字串引用,所以並非每次使用字串時都發生合併操作。

而IE7的實現機制更糟糕:

每連線一對字串都要把它複製到一塊新分配的記憶體中。

Array.join() 和 String.prototype.concat()

大多數瀏覽器中,陣列項合併比其他字串連線方法更慢

Array.join()當把所有的陣列的元素連線在一起時,瀏覽器會分配足夠的記憶體來存放整個字串,而且不會多次拷貝最終字串中相同的部分。

字串的原生方法concat()能接收任意數量的引數,並將每一個引數附加到所呼叫的字串上。但是多數情況下,使用concat()比使用簡單的++=稍慢,尤其在IE,Opera和Chrome中慢得更明顯。


在《高效能JavaScript》看到了就記錄一下,方便以後檢視。

相關文章