« thinkITでバグ管理についての連載始まりました。 | メイン | プルダウンについてちょっとだけ考える »

jQueryのパフォーマンスについて --- id アクセスとclass アクセス

最近、jQueryを利用して書かれたソースのパフォーマンスチェックをしていて、jQueryのソースも見つつ色々と分かってきました。

jQueryのパフォーマンス最適化に関するTips

で、↑このエントリで話題になっている

  • class指定だとid指定より遅くなる。
  • $('div#hoge') と $('#hoge') では、$('#hoge')の方が早い。

という2点について、その理由を解説します。

・class指定だとid指定より遅くなる。

javascript にはdocument.getElementById() という関数はありますが、class指定でHTMLElementを取得するメソッドは存在しません。

なので、class名で取得しようとした場合、検索対象のHTMLElementを総なめしてclass名をチェックする必要があります。

検索対象が多ければ多いほど当然遅くなっちゃいます。

・$('div#hoge') と $('#hoge') では、$('#hoge')の方が早い。

これは上記に関連するのですが、jQueryのソースを見ると、$('div#hoge') は document.getElementById()で値を取得するのではなく、まずdocument.getElementsByTagNames で検索対象のHTMLElementを取得して、それをfor文でまわして id 属性を文字列比較しています。

同じように、$('div.hoge') も 、class 属性を文字列比較して取得しています。

結論

  • 可能な限り$('#id') でid属性を指定して使おう。
  • class指定を使うときは対象を絞り込んでから。
  • $('tagName#id') と $('.class') はダメ。絶対。

余談

結論として$('tagName#id') は使っちゃダメって話なんですが、$('div.hoge') とどっちが早いのか。

僕の環境では $('tagName#id') の方が早かったです。

ソースを見ると、id はhtml中で一意ということで、for文でチェックしつつ見つかったら breakでfor文を抜けていますが、classの場合全部チェックしないといけないので、その分の差かもしれません。

あと、class は class = "hoge moge" のようにスペース区切りで複数指定できるので、jQueryのソースでは指定したclass名の前後に半角スペースを付け、チェック対象のHTMLElementのclassName 属性値の前後にも同様に半角スペースを付けて、indexOf でチェックしています。

↓$('tagname#id')で id でチェックしているところ

var tmp=[];
for(var i=0;r[i];i++)
  if(r[i].getAttribute("id")==m[2]){
    tmp=[r[i]];
    break;
  }
r=tmp;

↓$('tagname.class')で class名 でチェックしているところ

// r がチェック対象のオブジェクト、mがチェックするclass名、
// not がbool値でtrue:mのclass名が該当しないものをリターン,false:mのclass名が該当するものをリターン
classFilter:function(r,m,not){
  m=" "+m+" ";
  var tmp=[];
  for(var i=0;r[i];i++){
   var pass=(" "+r[i].className+" ").indexOf(m)>=0;
   if(!not&&pass||not&&!pass)tmp.push(r[i]);
  }
  return tmp;
}

この辺の泥臭い処理もベンチマークの結果に効いてくるのかもしれません。

にしても、jQueryおもしろい。なんか書いていて楽しくなりますね。