jQueryでセレクタで指定するのとfilter()で絞るの、どっちがいいか。

すごい久しぶりの更新になってしまいました。

さて、jQueryには画像をスタイリッシュに表示するLightbox系のプラグインがたくさんありますね。そのプラグインを、画像へリンクしているa要素に適用させたいとします。いちいちclassやrelを振るのは面倒ですものね。

そんなとき、セレクタで指定するのと、filterで指定するの、パフォーマンス的にどっちがいいのかな、と思って試してみました、という軽い話です。

前提

次のようなhtmlで、画像へリンクしているa要素だけを取得したいとします。画像へのリンクかどうかは、a要素のhref属性の拡張子を見て判断します。

<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<p><a href="sample01.jpg">sample01.jpg</a></p>
<p><a href="sample02.jpeg">sample02.jpeg</a></p>
<p><a href="sample03.png">sample03.png</a></p>
<p><a href="sample04.gif">sample04.gif</a></p>
<p><a href="sample05.pdf">sample05.pdf</a></p>
<p><a href="sample06.html">sample06.html</a></p>
<p><a href="sample07.htm">sample07.htm</a></p>
<p><a href="sample08.JPG">sample08.JPG</a></p>
<p><a href="sample09.JPEG">sample09.JPEG</a></p>
<p><a href="sample10.cgi">sample10.cgi</a></p>

ここで注意したいのは、CMSでサイトを管理しているとき、デジカメで撮った写真などをアップロードすると、拡張子が「JPG」や「JPEG」というように大文字になることが考えられます。したがって、拾う拡張子は、次の種類が考えられます。

  • jpg, jpeg, JPG, JPEG, png, gif

さて、いくつか書き方を見ていきます。

なお、パフォーマンスは、「jsPerf — JavaScript performance playground」というサイトで、Firefox 7.0.1 on Mac OS X 10.6でチェックしました。「回数」というのは1秒当たりに実行できた回数を意味します(あくまで目安です)。

セレクタでカンマ区切りでつなげる

たぶん、一番シンプルというか分かりやすい書き方はこれだと思います。

$('a[href$="jpg"],a[href$="jpeg"],a[href$="JPG"],a[href$="JPEG"],a[href$="png"],a[href$="gif"]').hide();

回数:2,933回

で、なんとなくこれが一番パフォーマンス悪いような気がしてましたが、すいません、一番高速でした。さすが、jQuery。

基本の書き方ですので、誰でもすぐに分かると言うメリットがありますね。

filter()にセレクタを指定して絞る

次に、filter()にセレクタを指定して絞ります。

$('a').filter('[href$="jpg"],[href$="jpeg"],[href$="JPG"],[href$="JPEG"],[href$="png"],[href$="gif"]').hide();

回数:1,031回

残念ながら、これが一番パフォーマンスが悪かったです。まあ、今回のケースでは、この書き方はあまりしないような気もします。

filter()で関数を実行して絞る(1)

これが一番プログラマーっぽい気がしていますが、どうでしょうか。(@reaさんに(2)の書き方を、@rewishさんに(3)の書き方をアドバイスいただきました。そちらの方がスマートです!)

$('a').filter(function(){
    return this.href.toLowerCase().match(/\.(jpg|jpeg|png|gif)$/);
}).hide();

回数:1,442回

まあまあですね。この書き方だと.toLowerCase() メソッドを使って全部小文字にしてからチェックするので、大文字、小文字を別々に指定する必要がないという、僅かなメリットがあります。

filter()で関数を実行して絞る(2)

toLowerCase()を使わないで、正規表現の「 i 」オプションを使うパターンです。i オプションを付けることによって大文字と小文字は無視されます。

$('a').filter(function(){
    return this.href.match(/\.(jpg|jpeg|png|gif)$/i);
}).hide();

回数:1,442回

シンプルになっていいですね〜。

filter()で関数を実行して絞る(3)

これが一番かっこいいです。そもそも、正規表現のjpegの部分は全部これでいいんですよね。まだまだ引き出しが経験値が足りないな、自分。

$('a').filter(function(){
    return /\.(jpe?g|png|gif)$/i.test(this.href);
}).hide();

回数:1,442回

こういうのがすぐに出てくるようになりたいです。

まとめ

ということで、結局一番シンプルというか、ノーマルというか、セレクタをカンマで区切って列挙する基本的な書き方が一番パフォーマンスが良いようです。

もちろん、状況によって結果は全然変わってくるのでしょうが、このあたりは、あまり難しいことを考えずに、シンプルにセレクタを指定すれば良いのかもしれない、という気がしました。

  • このエントリーをはてなブックマークに追加
Just a second...