你必須知道的JavaScript 中字符串連接的性能的一些問題
而JavaScript的核心是ECMAScript 。與其他語言類似,ECMAScript 的字符串是不可變的,即它們的值不能改變。
請考慮下面的代碼:
var str = "hello ";
str += "world";實(shí)際上,這段代碼在幕后執(zhí)行的步驟如下:
1.創(chuàng)建存儲 "hello " 的字符串。
2.創(chuàng)建存儲 "world" 的字符串。
3.創(chuàng)建存儲連接結(jié)果的字符串。
4.把 str 的當(dāng)前內(nèi)容復(fù)制到結(jié)果中。
5.把 "world" 復(fù)制到結(jié)果中。
6.更新 str,使它指向結(jié)果。
每次完成字符串連接都會執(zhí)行步驟 2 到 6,使得這種操作非常消耗資源。如果重復(fù)這一過程幾百次,甚至幾千次,就會造成性能問題。解決方法是用 Array 對象存儲字符串,然后用 join() 方法(參數(shù)是空字符串)創(chuàng)建最后的字符串。想象用下面的代碼代替前面的代碼:
var arr = new Array();
arr[0] = "hello ";
arr[1] = "world";
var str = arr.join("");
這樣,無論數(shù)組中引入多少字符串都不成問題,因?yàn)橹辉谡{(diào)用 join() 方法時才會發(fā)生連接操作。此時,執(zhí)行的步驟如下:
1.創(chuàng)建存儲結(jié)果的字符串
2.把每個字符串復(fù)制到結(jié)果中的合適位置
雖然這種解決方案很好,但還有更好的方法。問題是,這段代碼不能確切反映出它的意圖。要使它更容易理解,可以用 StringBuffer 類打包該功能:
function StringBuffer () {
this._strings_ = new Array();
}
StringBuffer.prototype.append = function(str) {
this._strings_.push(str);
};
StringBuffer.prototype.toString = function() {
return this._strings_.join("");
};
這段代碼首先要注意的是 strings 屬性,本意是私有屬性。它只有兩個方法,即 append() 和 toString() 方法。append() 方法有一個參數(shù),它把該參數(shù)附加到字符串?dāng)?shù)組中,toString() 方法調(diào)用數(shù)組的 join 方法,返回真正連接成的字符串。要用 StringBuffer 對象連接一組字符串,可以用下面的代碼:
var buffer = new StringBuffer ();
buffer.append("hello ");
buffer.append("world");
var result = buffer.toString();
基于上面的實(shí)現(xiàn)我們來進(jìn)行一下運(yùn)行時間對比,即以“+”逐個進(jìn)行字符串連接和我們封裝的工具。可用下面的代碼測試 StringBuffer 對象和傳統(tǒng)的字符串連接方法的性能,在chrome控制臺輸入一下代碼并運(yùn)行:
var d1 = new Date();
var str = "";
for (var i=0; i < 10000; i++) {
str += "text";
}
var d2 = new Date();
console.log("Concatenation with plus: "
+ (d2.getTime() - d1.getTime()) + " milliseconds");
var buffer = new StringBuffer();
d1 = new Date();
for (var i=0; i < 10000; i++) {
buffer.append("text");
}
var result = buffer.toString();
d2 = new Date();
console.log("Concatenation with StringBuffer: "
+ (d2.getTime() - d1.getTime()) + " milliseconds");
這段代碼對字符串連接進(jìn)行兩個測試,第一個使用加號,第二個使用 StringBuffer 類。每個操作都連接 10000 個字符串。日期值 d1 和 d2 用于判斷完成操作需要的時間。請注意,創(chuàng)建 Date 對象時,如果沒有參數(shù),賦予對象的是當(dāng)前的日期和時間。要計算連接操作歷經(jīng)多少時間,把日期的毫秒表示(用 getTime() 方法的返回值)相減即可。這是衡量 JavaScript 性能的常見方法。該測試的結(jié)果可以幫助您比較使用 StringBuffer 類與使用加號的效率差異。
上例運(yùn)行結(jié)果如下:

那么有人也許會說JavaScript的String對象中不是也封裝一個concat()方法么,我們在下面也來用concat()方法來做同樣的事情,在consoel輸入以下代碼:
var d1 = new Date();
var str = "";
for (var i=0; i < 10000; i++) {
str.concat("text");
}
var d2 = new Date();
console.log("Concatenation with plus: "
+ (d2.getTime() - d1.getTime()) + " milliseconds");
我們可以看到做10000次字符竄連接它的耗時是:

由此可以得出結(jié)論,當(dāng)涉及到一定數(shù)量的字符串連接時,我們在Javascript中封裝一個類似Java中的StringBuffer對象(函數(shù))來進(jìn)行操作會在性能上得到提升。
相關(guān)文章
JavaScript數(shù)據(jù)結(jié)構(gòu)和算法之二叉樹詳解
這篇文章主要介紹了JavaScript數(shù)據(jù)結(jié)構(gòu)和算法之二叉樹詳解,本文講解了二叉樹的概念、二叉樹的特點(diǎn)、二叉樹節(jié)點(diǎn)的定義、查找最大和最小值等內(nèi)容,需要的朋友可以參考下2015-02-02
淺談JavaScript數(shù)據(jù)類型及轉(zhuǎn)換
本文向大家簡單介紹了javascript的數(shù)據(jù)類型以及他們直接的轉(zhuǎn)換方法,雖然沒有太多示例,但是也是個人的一些經(jīng)驗(yàn)總結(jié),這里推薦給大家。2015-02-02
JavaScript之?dāng)?shù)組(Array)詳解
這篇文章主要介紹了JavaScript之?dāng)?shù)組(Array)詳解,本文詳細(xì)講解了JavaScript數(shù)組的創(chuàng)建、檢測數(shù)組、轉(zhuǎn)化方法、棧方法、隊(duì)列方法、重排序方法、操作方法、位置方法等內(nèi)容,需要的朋友可以參考下2015-04-04
JS?數(shù)組sort方法的升序?yàn)槭裁词莂-b你知道嗎
這篇文章主要為大家詳細(xì)介紹了JS?數(shù)組sort方法為什么升序是a-b,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-02-02
javascript定義變量時有var和沒有var的區(qū)別探討
定義變量時省略var是不安全的,不過是合法的。定義的變量的作用域取決于定義的位置2014-07-07
你需要知道的10個最佳javascript開發(fā)實(shí)踐小結(jié)
Javascript的很多擴(kuò)展的特性是的它變得更加的犀利, 同時也給予程序員機(jī)會創(chuàng)建更漂亮并且更讓用戶喜歡的網(wǎng)站2012-04-04

