以下のスライドを意訳したものです。Compress周りについては触れていません。「いやいや、最新の書き方だともっと良い書き方があるんだよ!」という方のコメントをお待ちしております!
http://www.slideshare.net/paul.irish/perfcompression
クエリをキャッシュする
// 悪い例
var id = $("#content").data("id");
var itemId = $("#content").data("item-id");
// 良い例
var content = $("#content")
var id = content.data("id");
var itemId = content.data("item-id");
HTMLを生成するときにjQueryオブジェクトにアクセスし続けない
// 悪い例
$.each(reallyLongArray, function(count, item) {
var newLi = '<li>' + item + '</li>';
$('#ballers').append(newLi);
});
// 良い例 : DocumentFragmentを使用
var frag = document.createDocumentFragment();
$.each(reallyLongArray, function(count, item) {
var newLi = '<li>' + item + '</li>';
frag.appendChild(newLi[0]);
});
$('#ballers')[0].appendChild(frag);
// 良い例 : Stringを使用
var myhtml = "";
$.each(reallyLongArray, function(count, item) {
myhtml += '<li>' + item + '</li>';
});
$('#ballers').html(myhtml);
Keep things DRY
// 悪い例
if ($ventfade.data('currently') != 'showing') {
$ventfade.stop();
}
if ($venthover.data('currently') != 'showing') {
$venthover.stop();
}
if ($spans.data('currently') != 'showing') {
$spans.stop();
}
// 良い例
var elems = [$ventfade, $venthover, $spans];
$.each(elems, function(k, v){
if (v.data('currently') != 'showing') {
v.stop();
}
});
アンチパターン:オブジェクトリテラルを使わない宣言
無名関数で定義されているせいで、どこで何が起こっているのか判断がつかなくなってしまうケース。
$(document).ready(function() {
...
$('#magic').click(function(e) {
$('#yayeffects').slideUp(function() {
...
});
});
$('#happiness').load(url + ' #unicorns', function() {
...
});
});
オブジェクトリテラルを使用して記述するようにする。
var PI = {
onReady: function() {
...
$('#magic').click(PI.candyMtn);
$('#happiness').load(url + ' #unicorns', PI.unicornCb);
},
candyMtn: function(e) {
$('#yayeffects').slideUp(PI.slideCb);
},
slideCb: function() {
...
},
unicornCb: function() {
...
}
};
オブジェクトリテラルを使用することで、下記の利点を得られる。
- コードの見通しがよくなる。
- プロファイラで関数名を参照できる。
- 各関数をコンソールで実行してみることができる。
- 無名関数のときと比べて、テストが書きやすくなる。
アンチパターン:再クエリ
// create and append your element
$(document.body).append('<div class="baaron" />');
// requery to bind stuff
$("div.baaron").click(function(){ … });
// better
// swap to appendTo to hold your elem
$('<div class="baaron" />')
.appendTo(document.body)
.click(function(){ … });
$('#whats .the', context)
// パフォーマンスはこっちよりも
var arms = $('div.robotarm', '#container');
// こっちの方がいい
var arms = $('#container').find('div.robotarm');
// 読みやすさ的にはcontext?好みの問題かも。。
セレクタのパフォーマンス最適化
一番パフォーマンスが良いのは#idから下降する書き方。
// 普通の書き方
var arms = $('#container div.robotarm');
// もっと良い書き方
var arms = $('#container').find('div.robotarm');
不必要なセレクタを挟まないほうが、より高速にヒットする。
// 余計なものが混じっている
.data table.attendees td.gonzalez
// 中間をはぶこう
.data td.gonzalez
ユニバーサルセレクタはパフォーマンスを劣化させる。明示的に書いていなくても、暗黙のユニバーサルセレクタが使われている場合があるので、注意すること。
$('.buttons > *') // 超コストがかかる
$('.buttons').children() // 良い例
$('.gender :radio') // 暗黙のユニバーサルセレクタが含まれている
$('.gender *:radio') // 上記と同じ意味になる
$('.gender input:radio') // 良い例
効率的なCSSの書き方(https://developer.mozilla.org/ja/Writing_Efficient_CSS)
イベントのデリゲート
live()を使うより、delegate()を使うことでより高速化できる。
// 汚い書き方。。
$('a.trigger', $('#container')[0]).live('click', handerFn);
// 良い書き方
$('#container').delegate('click', 'a.trigger', handlerFn);
DOMの操作は総じて重い
タグのスタイル属性を直接操作するのはもってのほか。スタイルをいじりたい場合はクラスを変えよう。(DOMの操作は最小限におさえるのが原則)
ブラックボックスとしてjQueryを扱わない
単にjQueryを隠蔽する書き方は、単に可読性を下げるだけだ。
// これでは単にjQueryを隠蔽しているだけで、無駄にメソッドを増やしていだけに過ぎない。。
getScript: function( url, callback ) {
return jQuery.get( url, null, callback, "script" );
},
getJSON: function( url, data, callback ) {
return jQuery.get( url, data, callback, "json");
},
よく使うメソッドは覚えておこう。
map(), slice(), stop(), (de)queue(), prevAll(), pushStack(), inArray(), etc…
// index() in jQuery <= 1.3.2
$('#rdworth').parent().children().index( $('#rdworth')[0] )
// prevAll()を使うと10%速くなる
$('#rdworth').prevAll().length
// jQuery1.4からはこう書ける
$('#rdworth').index()
存在しない要素に対するアクションを書かないこと
jQueryは凄く空気を読んでくれるので、そんなコードを書いたとしてもエラーは出さない・・・けど、ものすごいオーバーヘッドが裏で生じることになる。
$('#doesntexist').slideUp()
// genFx(), speed(), animate()といったメソッドが実行されるが、要素は存在しないため画面上では何の動きもあらわれない
便利なメソッド
eq(), first(), last()
var lastelem = $elems.eq(-1); // get()と同じ
$('#nav li:first') === $('#nav li').first();
$('#nav li:last') === $('#nav li').last();
data()
// 普通の書き方
$(elem).data(key, value);
// 10倍速い!
$.data(elem, key, value);