1

わかりましたので、プロトタイプの継承を希望どおりに機能させようとしています。いくつかの例を読みましたが、必要な要件の 1 つは、親クラスのメソッドを簡単に呼び出せることでした。そして、モジュール パターン+ jQuery ボイラープレート スタイルに従いたいと思います。ここでは、デフォルト、空でないコンストラクター関数、およびプロトタイプ関数があります。

;(function($, window, undefined){

    "use_strict";

    var defaultsHuman = {

        id: 1,

        age: 0
    };

    function Human( options ){

        this.options = $.extend(defaultsHuman, options || {});

        this.age = this.options.age;
        this.gender = 'male';

        //save originals for ref
        this._defaults = defaultsHuman;

    };
    Human.prototype = {

        _className: 'Human',

        init: function(){

            console.log('My class is ' + this._className + ' my gender is ' + this.gender + ' and my age is ' + this.age);

        }

    };

    //Right now Human's function prototype's constructor is Object(), but IE8 uses constructor.prototype
    //well now it's Object which is native so it's undefined?, anyways we lose the original reference to the constructor from the instance
    //so lets reset it to the constructor - constructor is now enumerable!

    Human.prototype.constructor = Human; //note this is cyclical!

    //END fn Human


    var defaultsChild = {

        name: ''

    };

    //we want to create a new constructor B that has properties, its constructor prototype is an instance of Human
    function Child( options ){

        //merge the parent defaults with my defaults, then extend dynamic options on top
        this.options = $.extend(this.constructor.prototype._defaults, defaultsChild, options || {});

        this.name = options.name;

        //A.call(this);

    };
    //new Human() calls Human's constructor and returns an object with prototype set to Human.prototype
    Child.prototype = new Human();

    $.extend(Child.prototype, {

        school: 'St. Peter\'s',

        init: function(){

            //create reference to super class
            this._super = this.constructor.prototype;

            //this._super.init.call(this);
            this._super.init();

            console.log('My name is ' + this.name + ' and my school is ' + this.school); 
        }

    });
        Child.prototype.constructor = Human;
    //END Child


    //export modules - old method before define
    window.Human = Human;
    window.Child = Child;

})(jQuery, window, undefined);



//some other closure somewhere where it is required in
;(function(window, undefined, Human, Child){

    "use_strict";

    var me = new Child({
        name: 'Clarence',
        age: 7
    }).init();


})(window, undefined, Human, Child);

私を混乱させているのは、Human's init関数では がインスタンスthisを参照しているHumanが、状態では がHuman constructor実行されていないため、静的に男性に設定されている性別さえ存在しないことです。

My class is Human my gender is undefined and my age is undefined 
My name is Clarence and my school is St. Peter's 

代わりに呼び出すことでこれを簡単に修正できthis._super.init.call(this);ます。おそらくこれを行うだけですが、まだ興味があります。

コンストラクターが実行された後、Child の関数プロトタイプを完全な Human オブジェクト に明示的に設定しますChild.prototype = new Human();。child の最終インスタンスを調べるとme、コンストラクターが実行された場所で (予想どおり) プロトタイプは HumanですがHuman initthis変数内では、人間のコンストラクターは実行したことがありません。

スーパーを参照this._super = this.constructor.prototype;すると、これはここで宣言されたプロトタイプへの参照ではありませんChild.prototype = new Human();か? そして、私が呼び出すthis.super.init()と、返されたもののコンテキストで実行されていませんnew Human()か?


また、IE8 との互換性のためにprotoを避けていることに注意してください。

4

1 に答える 1

1

これを正しく理解しているかどうかはわかりませんが、次のことができます。

function Human( options ){

    this.options = $.extend(defaultsHuman, options || {});

    this.age = this.options.age;
    this.gender = 'male';

    console.log("whaat",this.age);

    //save originals for ref
    this._defaults = defaultsHuman;

};
function Child( options ){
    Human.call(this, options);
};
Child.prototype = Object.create(Human.prototype);
function Human( options ){

    this.options = $.extend(defaultsHuman, options || {});

    this.age = this.options.age;
    this.gender = 'male';

    //save originals for ref
    this._defaults = defaultsHuman;

};

Object.create を持たない IE 8 以下またはそれ以前のブラウザーをサポートしたい場合は、polyfilを使用するか、コンストラクター関数による継承のためのヘルパー関数を持つこの回答をチェックしてください。

Human.prototype.init を呼び出すと、 のインスタンス値はありませんthisThis代わりに指しHuman.prototypeます。

  this.constructor === Human;
  this._super === this.constructor.prototype === Human.prototype;
  this._super.init === Human.prototype.init;

Child.prototype でデフォルトの Human 値を使用する場合は、Hukman が Child のすべてのインスタンスで共有されることを知っておく必要があります。その上で init を呼び出したい場合は、次のように実行できます。

    Child.prototype = Object.create(Human.prototype);
    Child.prototype.humanInstance = new Human();

    //... in the Child constructor body:
    this.humanInstance.init();
于 2013-08-23T03:10:51.733 に答える