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

那么有人也許會(huì)說JavaScript的String對(duì)象中不是也封裝一個(gè)concat()方法么,我們?cè)谙旅嬉瞾?lái)用concat()方法來(lái)做同樣的事情,在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次字符竄連接它的耗時(shí)是:

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

