JavaScriptでオブジェクトをDOMツリーに追加するとき、それぞれの方法で試してみました。
検証環境
- マシン:MacBook Air
- OS:Mac OS 10.6.6
- プロセッサ:1.86 GHz Intel Core 2 Duo
- メモリ:2GB 1067 MHz DDR3
- ブラウザ:Safari5
- 検証方法:3万回ループさせてオブジェクトを追加しています
- HTMLバージョン:HTML5(IE8以前には対応していません)
検証1:jQueryによるノーマルループ その1
まず、jQueryでULオブジェクトを生成して、そこへ3万回LIオブジェクトを追加した後、IDが「test」のDIVタグへ追加しています。
JavaScript
var doc=document;
function test(){
var n=doc.getElementsByName("num")[0].value; // デフォルトは30000回
doc.getElementById("test").innerHTML="";
// 動作検証開始
var t1=new Date();
var ul=$('<ul>');
for(var i=0;i<n;i++){
var li=$('<li>'+i+'</li>');
ul.append(li);
}
$('#test').append(ul);
// 動作完了時間を取得
var t2=(new Date())-t1;
doc.getElementById("time").innerHTML=String(t2)+'ミリ秒';
}
HTML
<div id="form_area"> ループ回数:<input type="text" name="num" class="num" value="30000" /> <input type="button" value="テスト開始" onclick="test()" /> </div> <div id="result">動作完了時間:<span id="time"></span></div> <div id="test" class="test_block"></div>
動作完了時間は、約3,494ミリ秒となりました。
検証2:jQueryによるノーマルループ その2
今度は、最初にjQueryで生成したULオブジェクトをIDが「test」のDIVタグへ追加してから、LIオブジェクトを3万回追加していきます。
JavaScript
var doc=document;
function test(){
var n=doc.getElementsByName("num")[0].value; // デフォルトは30000回
doc.getElementById("test").innerHTML="";
// 動作検証開始
var t1=new Date();
var ul=$('<ul>');
$('#test').append(ul);
for(var i=0;i<n;i++){
var li=$('<li>'+i+'</li>');
ul.append(li);
}
// 動作完了時間を取得
var t2=(new Date())-t1;
doc.getElementById("time").innerHTML=String(t2)+'ミリ秒';
}
HTML
<div id="form_area"> ループ回数:<input type="text" name="num" class="num" value="30000" /> <input type="button" value="テスト開始" onclick="test()" /> </div> <div id="result">動作完了時間:<span id="time"></span></div> <div id="test" class="test_block"></div>
動作完了時間は、約3,094ミリ秒となりました。
こっちの方が速度は速いみたいですが、何度かやってみたら微妙にバラつきがありました。
検証3:DIVの入れ子ループ
この状態から、DIVを複数回入れ子にした状態で検証してみます。
JavaScriptのソースコードはそのままです。
JavaScript
var doc=document;
function test(){
var n=doc.getElementsByName("num")[0].value; // デフォルトは30000回
doc.getElementById("test").innerHTML="";
// 動作検証開始
var t1=new Date();
var ul=$('<ul>');
$('#test').append(ul);
for(var i=0;i<n;i++){
var li=$('<li>'+i+'</li>');
ul.append(li);
}
// 動作完了時間を取得
var t2=(new Date())-t1;
doc.getElementById("time").innerHTML=String(t2)+'ミリ秒';
}
HTML
<div id="form_area"> ループ回数:<input type="text" name="num" class="num" value="30000" /> <input type="button" value="テスト開始" onclick="test()" /> </div> <div id="result">動作完了時間:<span id="time"></span></div> <div class="test_block"><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div> <div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div id="test"></div></div></div> </div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div> </div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div>
動作完了時間は、約3,239ミリ秒となりました。
DIVを入れ子にすると、若干処理が遅くなるようです。
検証4:ネイティブオブジェクトによるノーマルループ
では、jQueryのオブジェクトを使わずに、ULオブジェクトとLIオブジェクトをJavascriptのネイティブオブジェクトで生成してみます。
DIVタグへのアクセスもgetElementByIdを使います。
JavaScript
var doc=document;
function test(){
var n=doc.getElementsByName("num")[0].value; // デフォルトは30000回
doc.getElementById("test").innerHTML="";
// 動作検証開始
var t1=new Date();
var ul=doc.createElement('ul');
doc.getElementById("test").appendChild(ul);
for(var i=0;i<n;i++){
var li=doc.createElement('li');
li.innerHTML=i;
ul.appendChild(li);
}
// 動作完了時間を取得
var t2=(new Date())-t1;
doc.getElementById("time").innerHTML=String(t2)+'ミリ秒';
}
HTML
<div id="form_area"> ループ回数:<input type="text" name="num" class="num" value="30000" /> <input type="button" value="テスト開始" onclick="test()" /> </div> <div id="result">動作完了時間:<span id="time"></span></div> <div id="test" class="test_block"></div>
動作完了時間は、わずか約226ミリ秒!!
ちょっと速くなるだけだと思ってましたが、大分速度に差がついているようです。
jQueryによるノーマルループ その2 と比べると約1/10ほどの速さで動作していることがわかります。
検証5:ネイティブオブジェクトのループとjQueryの混合
jQueryのセレクタをまったく使わないというのも不便ですよね。
ということで、ULオブジェクトとLIオブジェクトをJavascriptのネイティブオブジェクトで生成して、最後にjQueryのappendメソッドで仕上げたらどうなるのでしょうか。
JavaScript
var doc=document;
function test(){
var n=doc.getElementsByName("num")[0].value; // デフォルトは30000回
doc.getElementById("test").innerHTML="";
// 動作検証開始
var t1=new Date();
var ul=doc.createElement('ul');
for(var i=0;i<n;i++){
var li=doc.createElement('li');
li.innerHTML=i;
ul.appendChild(li);
}
$('#test').append(ul);
// 動作完了時間を取得
var t2=(new Date())-t1;
doc.getElementById("time").innerHTML=String(t2)+'ミリ秒';
}
HTML
<div id="form_area"> ループ回数:<input type="text" name="num" class="num" value="30000" /> <input type="button" value="テスト開始" onclick="test()" /> </div> <div id="result">動作完了時間:<span id="time"></span></div> <div id="test" class="test_block"></div>
動作完了時間は、約226ミリ秒になりました。
Javascriptのネイティブメソッドのみを使った場合と比べて、速さはあまり変わらないようです。
結論
結果的には、ループして大量のオブジェクトを作成する場合は、JavascriptのネイティブメソッドであるcreateElementを使った方が効率が良いです。
その後、DOMツリーにオブジェクトを追加する場合は、Javascriptのネイティブでも、jQueryのセレクタを使っても、特に違いはなさそうでした。
jQueryでオブジェクトを生成するときに、少し負荷がかかるのかもしれません。