你必須知道的JavaScript 中字符串連接的性能的一些問(wèn)題
而JavaScript的核心是ECMAScript 。與其他語(yǔ)言類(lèi)似,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ù)這一過(guò)程幾百次,甚至幾千次,就會(huì)造成性能問(wèn)題。解決方法是用 Array 對(duì)象存儲(chǔ)字符串,然后用 join() 方法(參數(shù)是空字符串)創(chuàng)建最后的字符串。想象用下面的代碼代替前面的代碼:
var arr = new Array();
arr[0] = "hello ";
arr[1] = "world";
var str = arr.join("");
這樣,無(wú)論數(shù)組中引入多少字符串都不成問(wèn)題,因?yàn)橹辉谡{(diào)用 join() 方法時(shí)才會(huì)發(fā)生連接操作。此時(shí),執(zhí)行的步驟如下:
1.創(chuàng)建存儲(chǔ)結(jié)果的字符串
2.把每個(gè)字符串復(fù)制到結(jié)果中的合適位置
雖然這種解決方案很好,但還有更好的方法。問(wèn)題是,這段代碼不能確切反映出它的意圖。要使它更容易理解,可以用 StringBuffer 類(lèi)打包該功能:
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 類(lèi)。每個(gè)操作都連接 10000 個(gè)字符串。日期值 d1 和 d2 用于判斷完成操作需要的時(shí)間。請(qǐng)注意,創(chuàng)建 Date 對(duì)象時(shí),如果沒(méi)有參數(shù),賦予對(duì)象的是當(dāng)前的日期和時(shí)間。要計(jì)算連接操作歷經(jīng)多少時(shí)間,把日期的毫秒表示(用 getTime() 方法的返回值)相減即可。這是衡量 JavaScript 性能的常見(jiàn)方法。該測(cè)試的結(jié)果可以幫助您比較使用 StringBuffer 類(lèi)與使用加號(hào)的效率差異。
上例運(yùn)行結(jié)果如下:
那么有人也許會(huì)說(shuō)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è)類(lèi)似Java中的StringBuffer對(duì)象(函數(shù))來(lái)進(jìn)行操作會(huì)在性能上得到提升。
相關(guān)文章
Javascript & DHTML 實(shí)例編程(教程)基礎(chǔ)知識(shí)
Javascript & DHTML 實(shí)例編程(教程)基礎(chǔ)知識(shí)...2007-06-06淺談Web頁(yè)面向后臺(tái)提交數(shù)據(jù)的方式和選擇
下面小編就為大家?guī)?lái)一篇淺談Web頁(yè)面向后臺(tái)提交數(shù)據(jù)的方式和選擇。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-09-09JavaScript 中的日期和時(shí)間及表示標(biāo)準(zhǔn)介紹
本文為大家詳細(xì)介紹下時(shí)間標(biāo)準(zhǔn)指的是什么?UCT和GMT 的概念、關(guān)聯(lián)和區(qū)別?以及時(shí)間表示標(biāo)準(zhǔn)有哪些?感興趣的朋友可以參考下2013-08-08簡(jiǎn)介JavaScript中Math.cos()余弦方法的使用
這篇文章主要介紹了簡(jiǎn)介JavaScript中Math.cos()余弦方法的使用,是JS入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-06-06