Web/DB プログラミング徹底解説

ホーム > JavaScript プログラミング > JavaScript の文字列の結合を最適化する

JavaScript の文字列の結合を最適化する

Ajax プログラミングでは、サーバーから返されたデータを用いて HTML 要素 (テーブル等) を構築し、 それをあらかじめ用意されたプレースホルダー (div や span 要素など) に差し込むことがしばしば行われます。 特に JavaScript で文字列を結合する箇所についてどのように実装すれば、高速に処理可能であるか試しましたので、 この資料ではそのテスト方法と結果を示します。

実験準備 (ラッパークラスの作成)

当サイトの資料 Ajax プログラミング入門 でもちらっと紹介しましたが、 文字を結合する際には Array に文字列を push していき、最後に join('') によって結合するのが良いとの情報がありましたので、 その真偽を調べようと考えました。比較対象は単純な文字列の結合です。

Array はそのまま使うのではなく、薄いラッパーを書きました。TKStringBuffer というクラス名にし、push 操作を append という名のメソッドに置き換えています。また、join('') は JavaScript の流儀に従って toString() メソッドに置き換えています。TKStringBuffer の実装は下記の通りです。

function TKStringBuffer() {
	this.__buffer = new Array();
}

TKStringBuffer.prototype = {
	clear : function() { this.__buffer = new Array(); },
	append : function(s) { this.__buffer.push(s); },
	appendn : function(s) { this.append(s); this.append('\n'); },
	toString : function() {	return this.__buffer.join(''); },
	/* Alias */
	a : function(s) { this.append(s); },
	an : function(s) { this.appendn(s); }
}

実験: + 演算子による文字列の結合 vs Array.push, push, ..., Array.join('')

実験は以下のように文字列を指定回数足し算する場合と、Array.push を指定回数繰り返し最後に join('') する場合を比較します。

尚、TKStringBuffer のように Array() を明示的に new して、使う以外に

var a = [ 'a', 'b', 'c' ];

のようにして配列を作成する方法もあります。

Event.observe(window,'load',window_onload,false);

function window_onload(evt){

	Event.observe('btn1', 'click', btn1_onclick, false);
	Event.observe('btn2', 'click', btn2_onclick, false);

}

function get_cnt() {

	return parseInt($('cnt').value);

}

function get_teststr() {

	return $('txt').value;

}

function btn1_onclick(evt){

	var cnt = get_cnt();
	var txt = get_teststr();

	var start = (new Date()).getTime();
	
	var s = '';

	for(var i=0; i<cnt; i++){
		s += txt;
	}

	var start2 = (new Date()).getTime();

	$('str').innerHTML = s;

	var end = (new Date()).getTime();

	$('result_1a').innerHTML = (end - start);
	$('result_1b').innerHTML = (start2 - start);
	$('result_1c').innerHTML = (end - start2);
	$('result_1d').innerHTML = s.length;

}

function btn2_onclick(evt){

	var cnt = get_cnt();
	var txt = get_teststr();

	var start = (new Date()).getTime();

	var s = new TKStringBuffer();

	for(var i=0; i<cnt; i++){
		s.a (txt);
	}

	var start2 = (new Date()).getTime();

	$('str').innerHTML = s.toString();

	var end = (new Date()).getTime();

	$('result_2a').innerHTML = (end - start);
	$('result_2b').innerHTML = (start2 - start);
	$('result_2c').innerHTML = (end - start2);
	$('result_2d').innerHTML = (s.toString()).length;

}

以下のフォームを使って、実際に試していただけます。

結合回数:
結合文字:

テスト#説明結果
所要時間[ms]結合[ms]innerHTML 及び Array.join[ms]文字列長
テスト 1文字列の単純な結合
テスト 2TKStringBuffer を用いた文字列の結合

私の手元の環境は Windows Vista SP1 で、ブラウザは Internet Explorer 7 と Firefox 3 です。

結果: Array.push, push, ... , join('') の圧勝

実験結果は以下です。Firefox は常に高速。Internet Explorer は文字列の結合が極端に遅いことが確認できました。

Firefox では Array.push を使用した場合、逆にわずかに文字列の足し算より遅くなるようです。しかしその差はごくわずか (1000回の足し算で 1~2ms 程度) で、目くじら立てるほどのことはありません (ここを気にしてあれこれ手を打つくらいなら、 他にやることはあります)。

Internet Explorer では文字列の足し算が極端に遅く、Firefox ではどちらでもほぼ同じであることを考えると、 文字列は足し算するのではなく、Array.push と join を常に使っておくことが無難な実装といえそうです。