って記事をこないだ書きました。
予想以上にはてブされてて、みんなjQueryのこと大好きなんやなって思いました。
で、そのときにメモってたやつをまとめたら、それなりの長さになったのでついでに。
// これと $('#hoge', '#fuga'); // これ $('#fuga').find('#hoge');
どっちがどうでどうなるの?みたいな、たまに気になる記法についてです。
そもそも
こんなもんが何の得になるんじゃーってのはごもっともで。
最初に断っておくと、数あるクソコードのチューニング対象という切り口で見た時、
こんなものの最適化は序の口にすら当たりません。
そもそもDOMなんてキャッシュして使うもので、何回も取得なんてやらないのが鉄則。
で、その数少ないであろう取得時のお作法なので、そこまで役立つことはないと思います。
が、知ってて損はしないのでいちおう。
たまに気になる記法の違いたち
$(selector, context) === $(context).find(selector)
// 実行されるコードはいっしょ
$(selector, context);
$(context).find(selector);
これはソースコードに書いてある通りですね。
contextが指定されてた場合、それでもってfindします。
まあcontextをキャッシュして使いまわせるシーンでは、
後者のようにfindする方が速くて良いです。
$(selector, context) vs $(context).find(selector)
というわけなので、
<div id="parent"> <span class="child">C1</span> <span class="child">C2</span> </div>
って場合に、
// 既に親がキャッシュされてたとしたら var $parent = $('#parent'); $('.child'); // ってするのがいいのか $parent.find('.child'); // ってするのがいいのか
さて、どっちでしょう!
正解は、
- findしようとする相手がidセレクタで捕まるなら、$('#id') で取るべし(contextはいらない)
- その他の場合は、検索範囲を絞ることができる後者、findで取るべし
詳しい理由は次へ。
doc.getElementsByClassName vs context.getElementsByClassName
そもそもなDOMのSelectorAPI的な話ですが、コンテキストは指定した方が速い。
対象がidの場合は、そもそもdocument.getElementByIdであって、context.getElementByIdではない(ってかできない)。
原則DOMはキャッシュして欲しいので、出来る限りcontextを囲い込むべしってことですね。
もちろんTPOはありますけど!
$('.hoge') vs $('span.hoge')
// <span class="hoge">これを取る場合に</span> // こうするか $('.hoge'); // こうしたほうがいいのか $('span.hoge');
これよく見ますねー。
なんか厳密に指定したほうが速くなるような気が・・大きなお世話です!
実装として、
- 単一のidでもclassでもtagとも判定できない文字列は、もれなくquerySelectorAllされる
- よって、getElementsByClassNameで済んだセレクタなのに、querySelectorAllされちゃう
よって、前者のが速い。
$('.hoge #fuga')みたいなやつも遅くなるだけなのでやめてあげてください。
最後に言い訳
つらつらと書いてきましたがこの記事は、
- querySelectorAllよりもgetElementsByClassNameの方が速い
- メソッドコールが少ない = 速い
といったニュアンスで書いてるので、これが当てはまらない環境では相容れない知識です。
まあIE6とか7とか相手にする時代ならともかく、今はだいたいこの認識で間違いないような?と思ってますが。
少なくとも手元のiPhone4/5/6では、圧倒的にquerySelectorAllが遅かったし・・。
ちなみに、抑えておくべき情報は2011年に全て書いてありました。
jQueryのCSSセレクタAPIを高速に扱う方法 | tech.kayac.com - KAYAC engineers' blog
実は公式にも似たような情報がありました・・!