てっく煮ブログさんのエントリー
jQuery を高速に使う CSS セレクタの書き方 - てっく煮ブログ
をみてて、jQuery の $("#xxxx") を速くしたいと考えていたことを思いだした。それについて書く。
jQuery の $("#xxxx") について
セレクタをどう処理しているのか jquery-1.2.6.js で確認してみよう。
まず下記の init が $() に相当する。Handle HTML stringsのところで引数が string だと quickExpr.exec が走る。これは正規表現でのセレクタ解析処理である。
その後、HANDLE: $("#id")のところでマッチして取得した ID を使って、var elem = document.getElementById 使い、それを return jQuery(elem) として再び init が呼び出される。
jQuery.fn = jQuery.prototype = { init: function( selector, context ) { // Make sure that a selection was provided selector = selector || document; // Handle $(DOMElement) if ( selector.nodeType ) { this[0] = selector; this.length = 1; return this; } // Handle HTML strings if ( typeof selector == “string” ) { // Are we dealing with HTML string or an ID? var match = quickExpr.exec( selector ); // Verify a match, and that no context was specified for #id if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) if ( match[1] ) selector = jQuery.clean( [ match[1] ], context ); // HANDLE: $("#id") else { var elem = document.getElementById( match[3] ); // Make sure an element was located if ( elem ){ // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id != match[3] ) return jQuery().find( selector ); // Otherwise, we inject the element directly into the jQuery object return jQuery( elem ); } selector = []; } // HANDLE: $(expr, [context]) // (which is just equivalent to: $(content).find(expr) } else return jQuery( context ).find( selector ); // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) return jQuery( document )[ jQuery.fn.ready ? “ready” : “load” ]( selector ); return this.setArray(jQuery.makeArray(selector)); },
よって、コストがかかっているのは正規表現の解析部分のようなのでこの部分を飛ばして、いきなり jQuery に DOM ノードを渡してあげると速くなりそうだ。
高速化方法とまとめ
IDによる jQuery オブジェクトの取得を下記のように定義しておくと簡単に速くできそうだ。($$ にしたのは prototype.js が $(“xxx”) で取れたりそれっぽいから)
function $$(id) { return $(document.getElementById(id)); }
(追記)上記の $$ の定義では、指定した ID が DOM ツリーに存在しないときの処理を考慮していない。
Windows Vista SP1 での計測実験 / 1000回実行の計測三回平均
IE 7.0
Firefox 3.0
Opera 9.6
Safari 3.2
jQuery $("#id")
707 ms
301 ms
157 ms
129 ms
document.getElementById(“id”)
201 ms
43 ms
35 ms
21 ms
jQuery $$(“id”)
470 ms
126 ms
53 ms
51 ms
document.getElementById は参考値としてです。いずれもブラウザでも $$ による取得の方が速くなっていることがわかる。ただ、IE では他のブラウザほど速くならなかったのが残念だ。
セレクタで ID を指定して取得を行うことはよくある。アプリの規模によってはこういった高速化を施しておくのも良いだろう。
テスト用のHTML
上記の計測に使った HTML ソースをべた貼りしておく。
テスト回数 :
テストノード 取得テスト用 dummy
var d = $("#dummy");
var d = document.getElementById("dummy");
function $$(id) {
return $(document.getElementById(id));
}
var d = $$("dummy");
alert($$("dummy").find(".best").text());
jQuery 1.3 において(2009/1/18 追記)
上記を jquery-1.3.min.js に差し替えて計測してみましたが、変わらずでした。