jQueryソース分析7-分離コンストラクタ

1762 ワード

ぶんりコンストラクタ
newオペレータによってオブジェクトを構築するには、一般的に4つのステップを経ます.
A.新しいオブジェクトを作成する
B.コンストラクション関数の役割ドメインを新しいオブジェクトに割り当てる(したがってthisはこの新しいオブジェクトを指す)
C.コンストラクション関数のコードの実行
D.この新しいオブジェクトを返す
最後に、新しいオブジェクトを返すだけでいいことを示します.実はnewオペレータは主にプロトタイプチェーンをインスタンスのthisに関連付けることが最も重要なので、プロトタイプチェーンが必要な場合はnewオペレータで処理しなければなりません.そうでなければthisはwindowオブジェクトになります.
 
jQueryのこの構造を分析します.以下は一般的なクラス式の書き方です.
var $$ = ajQuery = function(selector) {
    this.selector = selector;
    return this
}
ajQuery.fn = ajQuery.prototype = {
    selectorName:function(){
        return this.selector;
    },
    constructor: ajQuery
}
var a = new $$('aaa');  //   
a.selectorName() //aaa //       

 
まずjQueryのnewのないフォーマットを改造し、instanceofを通じてthisが現在のインスタンスであるかどうかを判断することができます.
var $$ = ajQuery = function(selector) {
    if(!(this instanceof ajQuery)){
        return new ajQuery(selector);
    }
    this.selector = selector;
    return this
}

 
しかし、以下のように書かないでください.
var $$ = ajQuery = function(selector) {
    this.selector = selector;
    return new ajQuery(selector);
}
Uncaught RangeError: Maximum call stack size exceeded

これにより、無限に自分に戻り、死の循環とオーバーフローをもたらします.
jQueryはこのようなデッドサイクルの問題を避けるために,プロトタイプ上のinit法をコンストラクタとして採用した.
var $$ = ajQuery = function(selector) {
    //     init     
    return new ajQuery.fn.init( selector );
}

ajQuery.fn = ajQuery.prototype = {
    name: 'aaron',
    init: function() {
        console.log(this)
    },
    constructor: ajQuery
}

これでループ再帰の問題は確実に解決されたが、また問題が来た.initはajQueryプロトタイプ上でコンストラクタとしての1つの方法であり、それではthisはajQueryではないので、thisはajQueryのプロトタイプを完全に引用できないので、ここではnewによってinitメソッドとajQueryを2つの独立したコンストラクタに分離する.