jquery.jsを読み解く

第1回 jQueryライブラリ(1~171行目)

この記事を読むのに必要な時間:およそ 6 分

はじめに

jQueryとは,John Resigによって開発され,最近非常に注目を集めている Javascriptライブラリです。 JavaScriptとHTMLの対話を劇的に改善し,Ajaxなどにより複雑化してきているWebアプリケーション構築に必要な処理を非常に簡潔に書くことができます。また,ブラウザの種類やバージョンによる違いも吸収してくれるため,プログラマの作業量も減らしてくれます。

本連載では,jQueryライブラリのコードを読みながら,実装として中で何が行われているのかを見ていこうと思います。

想定している読者は,jQueryライブラリをただ使うだけでなく,やっていることを理解したいという方,使われているコードを応用して自分なりの改造をしてみたい方,新たなプラグインを開発したいという方などです。

今回の連載では執筆開始時点の最新版であるバージョン1.2.2を対象としています。説明の都合上行番号に大きく依存しているため,最後までバージョン1.2.2を対象とすることになります。

jQuery ソースコードの入手

jQueryは,jquery-1.2.2.jsという数十KBの一つのファイルにすべて書かれています。このソースコードは,公式サイトからダウンロードできます。圧縮方法の違いによって3つのバージョンがあり,実際のサイトで利用するにはMinified版がお勧めなのですが,ソースコードの解説なのでここではUncompressed版を利用します。ぜひ,お手元にダウンロードして記事と一緒にご覧になってください。

Uncompressed 93KB 通常のソースコード(無圧縮)
Minified and Gzipped 51KB コメントや不要な空白を取り除いたもの
Packed 28KB Packerによって圧縮したもの

ローカルスコープ化

jQueryの良いところは,名前空間を汚染しないところです。すべての機能をロードした状態で,jQueryと$の2つのオブジェクトしか存在しません。このため,他のJavaScriptライブラリと混ぜて使うことができます。これを実現しているのが,ソースコードの最初に登場するこの部分です。

0001: (function(){
      ...
3383: })();

全体のコードが,(function(){...})() で囲まれています。初めて見ると不思議な感じがしますが,無名関数を定義してすぐに実行するという処理を行っています。関数は,ふつうhoge()のような形で呼び出しますが,最初の()で括られた部分がhogeにあたり,その後に引数なしの()が続くと説明すれば少し分かりやすいでしょうか。

これにより,すべての定義をローカルスコープに押し込めることに成功しています。

先頭のコメント, 著作権表示

0002: /*
0003:  * jQuery 1.2.2 - New Wave Javascript
0004:  *
0005:  * Copyright (c) 2007 John Resig (jquery.com)
0006:  * Dual licensed under the MIT (MIT-LICENSE.txt)
0007:  * and GPL (GPL-LICENSE.txt) licenses.
0008:  *
0009:  * $Date: 2008-01-14 17:56:07 -0500 (Mon, 14 Jan 2008) $
0010:  * $Rev: 4454 $
0011:  */
0012:

MITライセンスとGPLのデュアルライセンスで公開されています。あなたがパフォーマンスのためにスクリプトを圧縮したとしても,このクレジット表示は削除しないように注意しましょう。jQueryは,自ら"New Wave Javascript"と名乗るだけのことはあり,非常に興味深いライブラリです。深く読み進めるにつれて,このことが段々明らかになってくることでしょう。

初期化処理

0013: // Map over jQuery in case of overwrite
0014: if ( window.jQuery )
0015:     var _jQuery = window.jQuery;
0016:

14行目では,既にwindow.jQueryオブジェクトが存在するときは,_jQueryに一時的に格納しておきます。これは後で,noConflict()を呼び出したときに元の状態に戻すためです。

次に出てくるコードは jQueryの初期化の部分になります。522行目のコードも一緒に見た方が分かりやすいので,順番は前後してしまいますが,ここで一緒に説明することにします。

0017: var jQuery = window.jQuery = function( selector, context ) {
0018:     // The jQuery object is actually just the init constructor 'enhanced'
0019:     return new jQuery.prototype.init( selector, context );
0020: };
0021:
0522: // Give the init function the jQuery prototype for later instantiation
0523: jQuery.prototype.init.prototype = jQuery.prototype;

17行目がまさにjQueryの根幹となる部分で,ここでjQueryオブジェクトを定義しています。jQueryオブジェクトの実体はinitメソッドによるコンストラクタで,オブジェクトが生成された際にinit()メソッドを実行してインスタンスを返します。よって,jquery.jsのロード時には定義が行われるのみで,jQuery関数(もしくは$)が呼ばれて初めて jQueryのプロトタイプオブジェクトのinit()が実行され,処理が行われます。

また,523行目ではjQuery.prototype.init関数オブジェクトのプロトタイプにjQuery関数オブジェクトのプロトタイプを設定しています。どういうことかというと,jQuery.prototypeに定義された様々なメソッドやプロパティを継承することで,jQueryライブラリの特徴であるメソッドチェーンを実現しているのです。

この辺りのコードは1.2.2で大幅に書き換えられました。リリースノートによると,ここを改善することで$(DOMElement)の処理を3倍高速化できたそうです(38ms → 13ms)。

※この部分を理解するにはJavaScriptのプロトタイプ指向に関する知識が必要となるのですが,とても興味深い部分ですので,余裕があればECMAScriptの仕様書等を読んでみることをお勧めします。

0022: // Map over the $ in case of overwrite
0023: if ( window.$ )
0024:     var _$ = window.$;
0025:
0026: // Map the jQuery namespace to the '$' one
0027: window.$ = jQuery;
0028:

14行目と同様に,既にwindow.$オブジェクトが存在するときは,_$に一時的に格納しておきます。また,27行目でjQueryのショートカットを$に割り当てます。

0029: // A simple way to check for HTML strings or ID strings
0030: // (both of which we optimize for)
0031: var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;
0032: 
0033: // Is it a simple selector
0034: var isSimple = /^.[^:#\[\.]*$/;
0035:

パラメータによって処理を分岐するための正規表現です。quickExprは,パラメータがHTML文字列か単純なID指定かを判定するために,isSimpleはシンプルな選択の場合にパフォーマンスを最適化するための分岐用として利用されます。

著者プロフィール

山下英孝(やましたひでたか)

大学を卒業後,大手SIerに就職し,電機メーカーの研究所勤務を経て,ウノウに入社。1年半に渡ってWebサイトの開発,ディレクション,運用を経験した後に独立。2008年2月よりフリーエンジニアとして活動中。好きな言語はJavaScriptとPythonで,Linuxサーバ運用管理も得意。

ブログWeboo! Returns.

コメント

コメントの記入