jquery.jsを読み解く

第7回 jQueryライブラリ(1637行目~1794行目)

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

ここ最近,JavaScript開発者の間で「jQuery」はかなりの盛り上がりを見せていますが,ついにGoogle検索キーワードの人気でも「prototype.js」を上回ったようです。まだ使ったことがないという方も,ぜひこの機会に触れてみてはいかがでしょうか。まず試しに使ってみる→内部がどうなっているか気になる→jQueryのソースを読む,というプロセスを経ることでよりjQueryへの理解が深まるのではないかと思います。

jQueryとprototype.jsの人気(by Google Trends)

jQueryとprototype.jsの人気(by Google Trends)

さて,今回はjQuery.filterなどの内部処理用メソッドを説明していきます。

jQuery.classFilter()

1637:   classFilter: function(r,m,not){
1638:     m = " " + m + " ";
1639:     var tmp = [];
1640:     for ( var i = 0; r[i]; i++ ) {
1641:       var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
1642:       if ( !not && pass || not && !pass )
1643:         tmp.push( r[i] );
1644:     }
1645:     return tmp;
1646:   },
1647: 

jQuery.classFilterメソッドは,引数 r の要素から引数 m というクラス名が指定されている要素のみを抽出するメソッドです。1638行目および1641行目で,クラス名の前後に空白を付与してデリミタとして利用しています。また,1642行目のif文により,第3引数 not がtrueの場合は逆の動作になり,クラス m が指定されていない要素のみが返されます。

jQuery.filter()

jQuery.filterメソッドは,find(),filter()などから利用される内部処理用のメソッドです。長いのでいくつかに区切って見ていきましょう。

1648:   filter: function(t,r,not) {
1649:     var last;
1650: 
1651:     // Look for common filter expressions
1652:     while ( t && t != last ) {
1653:       last = t;
1654: 
1655:       var p = jQuery.parse, m;
1656: 
1657:       for ( var i = 0; p[i]; i++ ) {
1658:         m = p[i].exec( t );
1659: 
1660:         if ( m ) {
1661:           // Remove what we just matched
1662:           t = t.substring( m[0].length );
1663: 
1664:           m[2] = m[2].replace(/\\/g, "");
1665:           break;
1666:         }
1667:       }
1668: 
1669:       if ( !m )
1670:         break;
1671: 

1648行目から見ていきましょう。第1引数 t にセレクタ式,第2引数 r に要素配列が渡されてきます。第3引数 not はフィルタ条件を反対にするboolean値です。

1653行目でlastの値として,セレクタ式 t を設定しています。このセレクタ式内の文字列に対して繰り返し処理を行っていきます。順に処理を行いlastの値が変化していくため,lastの値が変化していなかったら終了となります。

1655行目のjQuery.parseは1421行目で定義されているセレクタ式評価用の正規表現になります。1657行目のfor文は,そのjQuery.parseの結果でマッチするものがあれば変数 m に格納して,マッチした文字列を除いたものをtに格納します。これ以降は,このマッチした文字列に対し処理を行っていきますので,マッチする文字列がなければ,1670行目にてwhileループを抜けます。

1672:       // :not() is a special case that can be optimized by
1673:       // keeping it out of the expression list
1674:       if ( m[1] == ":" && m[2] == "not" )
1675:         // optimize if only one selector found (most common case)
1676:         r = isSimple.test( m[3] ) ?
1677:           jQuery.filter(m[3], r, true).r :
1678:           jQuery( r ).not( m[3] );
1679: 
1680:       // We can get a big speed boost by filtering by class here
1681:       else if ( m[1] == "." )
1682:         r = jQuery.classFilter(r, m[2], not);
1683: 
1684:       else if ( m[1] == "[" ) {
1685:         var tmp = [], type = m[3];
1686:         
1687:         for ( var i = 0, rl = r.length; i < rl; i++ ) {
1688:           var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
1689:           
1690:           if ( z == null || /href|src|selected/.test(m[2]) )
1691:             z = jQuery.attr(a,m[2]) || '';
1692: 
1693:           if ( (type == "" && !!z ||
1694:              type == "=" && z == m[5] ||
1695:              type == "!=" && z != m[5] ||
1696:              type == "^=" && z && !z.indexOf(m[5]) ||
1697:              type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
1698:              (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
1699:               tmp.push( a );
1700:         }
1701:         
1702:         r = tmp;
1703: 

1674行目は,セレクタ式に「:not(selector)」の書式が含まれていた場合の処理で,第3引数notをtrueにして,自身のjQuery.filterメソッドを呼び出し直します。ただし,1676行目の三項式によりfoo#barのように「:」「#」「[」「.」を間に含む場合はnot()メソッドを利用します。

1681行目は,セレクタ式が「.foo」のようなクラス指定の場合の処理で,この場合はjQuery.classFilterメソッドを利用します。

1684行目は,[attribute=value]のような属性フィルタ式の場合の処理になります。1688行目で変数aに検索対象の要素を設定し,jQuery.propsまたは属性プロパティを直接参照して結果を変数zに格納します。値が見つからないか,attributeの値が href, src, selected の場合は,次にjQuery.attrメソッドを用いて値を取得します。そして1693行目ですが,関係演算子が 「=」「!=」「^=」「$=」「$=」「*=」「~=」の場合の処理を1つのif文だけで処理しています。論理演算子||や&&をうまく活用して,tこの条件に合致したものを配列に格納します。

著者プロフィール

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

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

ブログWeboo! Returns.

コメント

コメントの記入