[JavaScript] “jQueryのappend” と ”appendChild” との処理速度を比べてみた

[JavaScript] “jQueryのappend” と ”appendChild” との処理速度を比べてみた

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でオブジェクトを生成するときに、少し負荷がかかるのかもしれません。