jQueryソースコード解読:pushStackとendメソッドの役割

// 要素の配列をスタックにプッシュする
    // (新しいマッチした要素セットを返す)
    pushStack: function(elements) { // elementsは配列または配列風オブジェクト
      // 新しいjQueryマッチした要素セットを構築する
      var newSet = jQuery.merge(this.constructor(), elements);

      // 古いオブジェクトをスタックに追加 (参照として)
      newSet.prevObject = this;
      newSet.context = this.context;

      // 新しく形成された要素セットを返す
      return newSet; // jQueryノードオブジェクト
    },
jQueryノードオブジェクトをスタックにプッシュするこのメソッドは、ユーザーが直接使用することは少ないが、他のメソッドの内部実装でスタックの概念が利用されるため、理解しておく必要がある。 上記のコードと図から、$('div').pushStack($('span'))はspan要素をスタックに追加し、その結果として$('span')が返されることがわかる。 コードの書き方について詳しく説明する。var newSet = jQuery.merge(this.constructor(), elements); という行は、JavaScriptの高度なテクニックを示している。this.constructor()はjQuery()を意味する。thisはjQueryのインスタンスを指し、this.constructorはプロトタイプのconstructorプロパティがjQueryを指すためだ。この行の意味は、追加されたjQueryノードオブジェクトを空のjQueryノードオブジェクトとマージし、新しいjQueryノードオブジェクトを返すことである。その後、このオブジェクトにcontextプロパティとprevObjectプロパティを追加し、prevObject = this; で前のjQueryノードを格納する。このthisはinitを指し、新しいjQueryノードnewSetを返す。 **最も重要な点は、$(' ').pushStack(elem)を呼び出すたびに新しいスタックが作成され、elemが$(' ')に追加されることである。そして、新しいresオブジェクト全体が返される。補足として、$(' ')に複数のノードが存在する場合、複数のjQueryノードは同じレベルに属し、一つのjQueryノードが一つのレベルというわけではない。各スタックの最下層には$(document)があり、その下には何もない。返されるnewSetはinit{}である。**
   each: function(fn, params) {
      return jQuery.each(this, fn, params);
    },

    ready: function(callback) {
      // コールバックを追加
      jQuery.ready.promise().done(callback);

      return this;
    },

    slice: function() {
      return this.pushStack(arraySlice.apply(this, arguments));
    },

    first: function() {
      return this.eq(0);
    },

    last: function() {
      return this.eq(-1);
    },

    eq: function(index) {
      var length = this.length;
      var adjustedIndex = index < 0 ? index + length : index;
      return this.pushStack(adjustedIndex >= 0 && adjustedIndex < length ? [this[adjustedIndex]] : []);
    },

    map: function(transformFn) {
      return this.pushStack(
        jQuery.map(this, function(elem, i) {
          return transformFn.call(elem, i, elem);
        })
      );
    },

    end: function() {
      // スタックを一つ戻る。前のオブジェクトがなければ、空のjQueryオブジェクトを返す。
      return this.prevObject || this.constructor(null);
    },

    // 内部使用のみ。
    // Arrayのメソッドのように振る舞い、jQueryのメソッドではない。
    push: core_push,
    sort: [].sort,
    splice: [].splice
次に、each、ready、slice、first、last、eq、map、endなどの一般的なメソッドについて説明する。これらのメソッドは相互に依存関係を持つ。 eachループ:このeachループは$(' ').each()であり、$.each()をさらにラップしたものである。 ready:エントリーポイントであり、内部でラップされた関数を呼び出す。その関数の呼び出しの意味は、後で理解する必要がある。 slice:切り取り。スタックメソッドと配列のメソッドを借用する 'this.pushStack(arraySlice.apply(this, arguments));' ここでのthisは呼び出し元のthis、つまりinitを指す。arraySliceは[].sliceを指し、argumentsはパラメータのコレクションである。callはパラメータコレクションを直接使用できないため、一つずつ指定する必要がある。 eq: j = +i + (i < 0 ? len : 0); という一行で負数と正数のiの値を解決する。正数の場合は+i + 0、負数の場合は+i + jQueryノードオブジェクトの長さ(+は数値型への変換を意味する)。'return this.pushStack(j >= 0 && j < len ? [this[j]] : []);' は、j(処理後の数値)が[0, len)の範囲内であれば[this[j]]をスタックに追加し、そうでなければ[]をスタックに追加する(this[j]は生のDOMノードである)。返されたnewSetを通じて、目的のjQueryノードオブジェクトを取得する。 first、lastはeqを基に操作され、first:eq(0)、last:eq(-1)となる。 map:マッピング。jQuery.map()を呼び出す。 end:スタック内で一つ上のレベルに戻る 'return this.prevObject || this.constructor(null);' このprevObjectが存在すれば(つまり、一つ上のレベルに値があれば)それを返し、なければ$(null) => init {} を返す。

タグ: jQuery javascript DOM操作 メソッド

6月30日 23:04 投稿