最近、jQueryを利用して書かれたソースのパフォーマンスチェックをしていて、jQueryのソースも見つつ色々と分かってきました。
で、↑このエントリで話題になっている
- 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おもしろい。なんか書いていて楽しくなりますね。