13

JavaScriptでクラス階層を設計しています。これまでは問題なく動作しますが、オブジェクトが親クラスの「インスタンス」であるかどうかを判断する方法がわかりません。例:

function BaseObject(name){
    this.name = name;

    this.sayWhoAmI = function(){
        console.log(this.name + ' is a Derivation1 : ' + (this instanceof Derivation1));
        console.log(this.name + ' is a Derivation2 : ' + (this instanceof Derivation2));
        console.log(this.name + ' is a BaseObject : ' + (this instanceof BaseObject));
    };
}
function Derivation1(){
    BaseObject.apply(this, ['first derivation']);
}
function Derivation2(){
    BaseObject.apply(this, ['second derivation']);
}

var first = new Derivation1();
var second = new Derivation2();

first.sayWhoAmI();これをログに記録します:

first derivation is a Derivation1 : true
first derivation is a Derivation2 : false
first derivation is a BaseObject : false

これをsecond.sayWhoAmI();記録している間:

second derivation is a Derivation1 : false
second derivation is a Derivation2 : true
second derivation is a BaseObject : false

私は両方firstsecondオブジェクトがそれらがのインスタンスであると言うべきであるように感じますBaseObject

このためにJavaScriptが作成されていない可能性があることは理解していますが、それを実現する方法があるのではないかと思います。

4

1 に答える 1

11

呼び出しのみでBase.apply(...)は継承は設定されません。最初の引数に.apply設定するだけで、他には何もありません。this親コンストラクターを呼び出すことは重要ですが、それだけでは不十分です。

あなたがしなければならないのは、プロトタイプチェーンを適切に設定することです。つまり、Derivation1.prototypeから継承するものに設定する必要がありますBase.prototype

コンストラクター関数の各インスタンスはコンストラクター関数のプロトタイプを継承するため、次のようなコードが表示されます。

Derivation1.prototype = new Base();

これは悪い考えであり、その理由はすでにわかります。引数がインスタンス固有のプロパティ(この場合)Baseを設定することを期待しています。nameただし、これらのプロパティは、後で子コンストラクターで。を使用して初期化するため、気にしませんBase.apply(this, ...)

したがって、必要なのはオブジェクトを継承することだけです。Base.prototype幸いなことに、ECMASCript 5は、それを実行できる関数(polyfill)を定義しています。

 Derivation1.prototype = Object.create(Base.prototype);

これにより、を継承する新しいオブジェクトが作成されBase.prototypeます。ここで、元のプロトタイプを新しいオブジェクトに置き換えたので、次のconstructorように正しく指すようにプロパティを設定する必要がありDerivation1ます。

Derivation1.prototype.constructor = Derivation1;

以下は完全な例です。また、このフィドルTJ Crowderによるこの優れた回答もご覧ください。これは、基本的に同じ問題を説明していますが、おそらくより良い方法です。


function BaseObject(name){
    this.name = name;
}

// move properties shared by all instances to the prototype!
BaseObject.prototype.sayWhoAmI = function() {
    console.log(this.name + ' is a Derivation1 : ' + (this instanceof Derivation1));
    console.log(this.name + ' is a Derivation2 : ' + (this instanceof Derivation2));
    console.log(this.name + ' is a BaseObject : ' + (this instanceof BaseObject));
};

function Derivation1(){
    BaseObject.apply(this, ['first derivation']);
}

Derivation1.prototype = Object.create(BaseObject.prototype);
Derivation1.prototype.constructor = Derivation1;

// some useless method of the child "class"
Derivation1.prototype.someOtherMethod = function() {
    return 42;
};

var first = new Derivation1();
first.sayWhoAmI();

</ p>

于 2012-07-26T12:13:39.967 に答える