14のjQueryベストプラクティス

原文:14 Helpful jQuery Tricks, Notes, and Best Practices

良かったので翻訳してみました。かなりの意訳で、上手に訳せてない箇所も多いので詳しくは原文を参照してください。

1.メソッドはjQueryオブジェクトを返す

ほとんどのメソッドがjQueryオブジェクトを返すのが重要です。

これにより次のようなメソッドチェーンが可能になっています。

$someDiv  
  .attr('class', 'someClass')  
  .hide()  
  .html('new stuff');

jQueryオブジェクトを返すのがわかっていれば次のように分割して書くことも出来ます。

var someDiv = $('#someDiv'); 
someDiv.hide();  

次のように一行で書くことも出来ます。

var someDiv = $('#someDiv').hide();

jQueryオブジェクトは変数などにキャッシュして使いまわすようにしましょう。

2.Findセレクタ

jQueryはあなたがひどいセレクタを書いても最適化してくれます。ただ、これを気をつければもっと良いものにできるでしょう。

それは可能な限りfindメソッドを利用すること。

// Fine in modern browsers, though Sizzle does begin "running"  
$('#someDiv p.someClass').hide();  
 
// Better for all browsers, and Sizzle never inits.  
$('#someDiv').find('p.someClass').hide(); 

最近のブラウザはQuerySelectorAllに対応してセレクタを解釈できるるけど、IE6やIE7みたいに対応していないブラウザでは、Sizzle エンジンが利用されます。Sizzle エンジンではセレクタを分割し配列に格納してセレクタの右部から順にマッチする要素を検索します。

 ['#someDiv', 'p'];

セレクタの右部がidや要素のようにシンプルになればなるほどセレクタが高速化されます。

つまり、

これでセレクタが最適化されます。

コンテキストを変わりに使う?

セレクタのコンテキストを利用するのでもよいでしょう。

 $('.someElements', '#someContainer').hide(); 

コンテキストは内部的にはfindメソッドに置き換えられえるので。

$('#someContainer')  
  .find('.someElements')  
  .hide();

証拠

// HANDLE: $(expr, context)  
// (which is just equivalent to: $(context).find(expr)  
} else {  
	return jQuery( context ).find( selector );  
}

3.$(this)を乱用しない

DOMの知識がないとしばしば不要なことをやってしまいます。

$('#someAnchor').click(function() {  
// Bleh  
  alert( $(this).attr('id') );  
});

id属性を取得したいだけならjQueryオブジェクトを利用せず次のようにJavaScriptのみで記述すればよいです。

$('#someAnchor').click(function() {
	alert( this.id );
});

注意:次の3つの属性「src」「href」「style」はjQueryを通したほうがよいです。古いIEではgetAttributeが必要なので。

証拠

// jQuery Source  
var rspecialurl = /href|src|style/;  
// ...  
var special = rspecialurl.test( name );  
// ...  
var attr = !jQuery.support.hrefNormalized && notxml && special ?  
  // Some attributes require a special call on IE  
  elem.getAttribute( name, 2 ) :  
  elem.getAttribute( name );  

多数のjQueryオブジェクト

何度もDOMにアクセスしてjQueryオブジェクトを生成するのはよくないです。

$('#elem').hide();  
$('#elem').html('bla');  
$('#elem').otherStuff();

#elemはキャッシュして使いまわしましょう。

// This works better  
$('#elem')  
  .hide()  
  .html('bla')  
  .otherStuff();  
  
// Or this, if you prefer for some reason.  
var elem = $('#elem');  
elem.hide();  
elem.html('bla');  
elem.otherStuff();

4.Readyメソッドのショートカット

ドキュメントが準備できた際に実行したい命令は次の関数の中に記述します。

$(document).ready(function() {  
   // let's get up in heeya  
});

これは次のように短く書くことも出来ます。

$(function() {  
  // let's get up in heeya  
});

jQueryでは関数が読みこまれたら次のようにreadyメソッドを実行しています。

if ( jQuery.isFunction( selector ) ) {  
   return rootjQuery.ready( selector );  
}

5.あなたのコードを安全にするには

沢山のスクリプトを読み込む場合は他のコードと名前の衝突を防がなくてはいけません。すでに「$」が利用されていたらどうするか。

jQuery.noConflict()を利用しましょう。これで$を別の名前で利用できます。

var j = jQuery.noConflict();  
// Now, instead of $, we use j.  
j('#someDiv').hide();  
// The line below will reference some other library's $ function.  
$('someDiv').style.display = 'none';

ただし、このコードは他の人がみたらわかりにくいので注意が必要です。

次のように記述するとコードの内側で「jQuery」を「$」として利用できるようになります。

(function($) {  
  // Within this function, $ will always refer to jQuery  
})(jQuery); 

readyメソッドのコールバック関数に引数で「$」を与えて利用する方法もあります。

jQuery(document).ready(function($) {  
  // $ refers to jQuery  
});

6.よりスマートに

jQueryがJavaScriptであることを忘れてはいけません。

どういうことかというと、JavaScriptのfor文の最適化は非常に重要です。それはjQueryのeachメソッドにもいえます。なぜかというとeachメソッド内ではfor文が利用されているから。

次のようなコードはよろしくない。

someDivs.each(function() {  
  $('#anotherDiv')[0].innerHTML += $(this).text();  
  //to-R注意:次のコードじゃないと話がおかしくなるので上記のコードは間違いだと思う
  //$('#anotherDiv')[0].innerHTML += $(this).html();
});

1.anotherDivをeachの回数だけ捜している
2.eachのたびにinnerHTMLプロパティに2回もアクセスしている
3.eachのたびにjQueryオブジェクトを作っている


これは次のように最適化すればよいです。

var someDivs = $('#container').find('.someDivs'),  
    contents = [];  
 
someDivs.each(function() {  
  contents.push( this.innerHTML );  
});  
$('#anotherDiv').html( contents.join('') ); 

eachメソッドでは配列に格納しておくだけ。

このTIPSはjQueryというよりJavaScript全体に言えます。jQueryはあなたのひどいコードまで補正はしてくれません。

DocumentFragment(空のノード)の利用

空のノードを作成する方法もあります。

var someUls = $('#container').find('.someUls'),  
    frag = document.createDocumentFragment(),  
    li;  
  
someUls.each(function() {  
    li = document.createElement('li');  
    li.appendChild( document.createTextNode(this.innerHTML) );  
    frag.appendChild(li);  
});  
  
$('#anotherUl')[0].appendChild( frag ); 

JavaScriptを学ぶことで様々な最適化手法がわかってくるでしょう。

7.Ajaxメソッド

jQueryには様々なAjaxメソッドがあるけど$.ajaxのショートカットだから気にすることはないです。

例えば$.getJSONを利用すると

$.getJSON('path/to/json', function(results) {  
     // callback  
    // results contains the returned data object  
});

$.getが呼ばれるんです。

getJSON: function( url, data, callback ) {  
    return jQuery.get(url, data, callback, "json");  
}

$.getはさらに$.ajaxを呼んでいます。

get: function( url, data, callback, type ) {  
    // shift arguments if data argument was omited  
    if ( jQuery.isFunction( data ) ) {  
        type = type || callback;  
        callback = data;  
        data = null;  
    }  
  
    return jQuery.ajax({  
        type: "GET",  
        url: url,  
        data: data,  
        success: callback,  
          dataType: type  
    });  
} 

つまり、次のような$.getJSONは、

$.getJSON('path/to/json', function(results) {  
    // callback  
    // results contains the returned data object  
}); 

次のような$.ajaxと同じ意味です。

$.ajax({  
    type: 'GET',  
    url : 'path/to/json',  
    data : yourData,  
    dataType : 'json',  
    success : function( results ) {  
        console.log('success');  
    })  
});  

8.ネイティブのプロパティとメソッドを利用する

JavaScriptを学べばネイティブのプロパティに直接アクセスできるようになります。

var anchor = document.getElementById('someAnchor');  
// anchor.id  
// anchor.href  
// anchor.title 

ただ、DOMの検索はメンドクサイのでjQuery使いましょう。
でも、次のように書いてはいけません。

var href = $('#someAnchor').id;  

jQueryを利用してネイティブのプロパティやメソッドにアクセスする場合は次のように書かなくてはいけません。

// OPTION 1 - jQueryを使う  
var href = $('#someAnchor').attr('id');  
  
// OPTION 2 - DOMでアクセスする  
var href = $('#someAnchor')[0].id;  
  
// OPTION 3 - jQueryのgetメソッドを利用する 
var href = $('#someAnchor').get(0).id; 
 
// OPTION 3b - getでインデックスを指定しない場合 
anchorsArray = $('.someAnchors').get();  
var thirdId = anchorsArray[2].id;  

getメソッドはjQueryコレクションを配列に変換しますので。

9.PHPでAjaxリクエストかどうか判定する

Ajaxを利用する場合、サーバーサイドで本当にAjaxのアクセスかどうかを判定したほうが良い場合もあるでしょう。クローラーやブラウザから直接アクセスされると負荷が大変です。

JavaScriptでは$.ajaxメソッドでheaderを設定しておきましょう。

if ( !remote ) {  
    xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");  
}

PHPなどのサーバーサイドではheaderをチェックしてAjaxによるアクセスかどうか判定しましょう。

function isXhr() {  
  return $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';  
}

10.jQuery と $

jQuery と $ の不思議に思います?jQueryのソースコードの一番下に答えがありますよ。

window.jQuery = window.$ = jQuery;

jQuery と $はグローバルオブジェクトに保存されていますのでどこからもアクセスできますよ。

(to-R:ちょっとうまく訳せない)

11.jQueryの読み込み

何らかの理由でCDNがダウンした場合、次のように書いてるとローカルのjQueryを読み込んでくれます。

<!-- Grab Google CDN jQuery. fall back to local if necessary -->  
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>  
<script>!window.jQuery && document.write('<script src="js/jquery-1.4.2.min.js"><\/script>')</script> 

12.jQueryフィルター

独自のフィルターを作成することが出来ます。

$('p:first').data('info', 'value'); // populates $'s data object to have something to work with   
$.extend(jQuery.expr[":"], {  
	block: function(elem) {  
		return $(elem).css("display") === "block";
	},
	hasData : function(elem) {	
		return !$.isEmptyObject( $(elem).data() );	
	}  
});
 
$("p:hasData").text("has data"); // grabs paras that have data attached  
$("p:block").text("are block level"); // grabs only parag

「:hasData」はdataを持っている要素を絞り込み、「:block」はブロックレベル要素のみを絞り込みます。

13.hoverメソッドにひとつの関数

jQuery1.4からhoverメソッドで1つの関数を利用することが可能になりました。

$('#someElement').hover(function() {  
  // mouseover  
}, function() {  
 // mouseout  
});
$('#someElement').hover(function() {  
  // the toggle() method can be used here, if applicable  
});

toggle()のように利用できます。

14. 属性の設定

jQuery1.4から$()メソッドの第2引数で属性を設定できるようになりました。

Before

$('<a />')  
  .attr({  
    id : 'someId',  
    className : 'someClass',  
    href : 'somePath.html'  
  });

After

$('<a/>', {  
    id : 'someId',  
    className : 'someClass',  
    href : 'somePath.html'  
});

これは属性だけではなくてclickのようなイベントや textなどでも利用できます。

関連エントリー

jQuery基礎文法最速マスター
jQueryを良くする25のTIPS
8のjQueryのすごいTIPS
jQueryのコードを良くする5つのTIPS
jQueryを使ったサンプルコード

スポンサードリンク

«mixiチェックのチェックボタンを設置 | メイン | [書評]JavaScriptプログラマのためのWebデザイン入門»