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タグへ追加しています。
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)+'ミリ秒'; }
<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万回追加していきます。
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)+'ミリ秒'; }
<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のソースコードはそのままです。
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)+'ミリ秒'; }
<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
を使います。
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)+'ミリ秒'; }
<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メソッドで仕上げたらどうなるのでしょうか。
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)+'ミリ秒'; }
<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でオブジェクトを生成するときに、少し負荷がかかるのかもしれません。