2011-10-27 11 views
0

おそらく私はこれを間違っていると思います。私は基本クラスとそのクラスを継承する2つのクラスを設定したいと思います。しかし、それは、ある子供が他の子供のインスタンスであることを私に伝えている...それは正しいことができないのですか?私はここで間違って何をしていますか?プロトタイプの継承された子クラスが別の子クラスのインスタンスであるのはなぜですか?

function BaseClass(){} 
function Child1(){} 

Child1.prototype = BaseClass.prototype; 
Child1.prototype.constructor = Child1; 

function Child2(){} 
Child2.prototype = BaseClass.prototype; 
Child2.prototype.constructor = Child2; 

console.log((new Child1() instanceof Child2)); // true 
+0

にOOPの正しい実装になります。ここJSで継承を使用する多くの方法の優れたリソースです/www.3site.eu/doc/ –

答えて

2

Child1.prototype = BaseClass.prototype;

Child1.prototype = Object.create(BaseClass.prototype)

であるべき

プロトタイプオブジェクトを同じにしたくない場合は、継承元の新しいプロトタイプオブジェクトが必要ですBaseClass

Live Example

免責事項:Object.createはES5は、レガシープラットフォームのサポートのためにES5-shimを使用しています。

あなたはより徹底的に例を与えること:

// Create base prototype 
var Base = { 
    method: function() { 
    return this.things; 
    }, 
    constructor: function (things) { 
    this.things = things; 
    } 
}; 
// Link constructor and prototype 
Base.constructor.prototype = Base; 

// Create child prototype that inherits from Base 
var Child = Object.create(Base); 
// overwrite constructor 
Child.constructor = function (things) { 
    things++; 
    Base.constructor.call(things); 
} 
// Link constructor and prototype 
Child.constructor.prototype = Child; 

// Swap prototype and constructor around to support new 
ChildFactory = Child.constructor; 

var c = new ChildFactory(41); 
console.log(c.method()); // 42 

視覚:

var Base = { ... }

ここで我々は単にメソッドとプロパティを持つオブジェクトを作成します。このオブジェクトのインスタンスを作成したいと考えています。だからBaseは "クラス"であり、すべてのメソッドとプロパティはインスタンス(constructorを含む)からアクセスできます。

Base.constructor.prototype = Base;

あなたはプロトタイプオブジェクトと一緒にあなたのオブジェクトConstructorFunction.prototypeの新しいインスタンスを与えるあなたはnewで呼び出すことができる機能である「コンストラクタ関数」をリンクする必要があります。これは基本的にあなたが手作業で行う必要がある接着剤です。なぜなら、ESはこれをあなたのためにしていないからです。

これを忘れた場合、コンストラクタ関数(X.constructor)には、インスタンスを継承するための.prototypeプロパティがありません。

var Child = Object.create(Base);

その[[Prototype]]Baseある新しいオブジェクトを作成します。これは基本的に今、私たちは子供のインスタンスが継承するメソッドです私たちの子オブジェクトにプロパティを追加するには、プロトタイプチェーン

Child -> ([[Prototype]] = Base) -> ([[Prototype]] = Object.prototype) -> null 

Child.x = ...

の始まりです。基本的には、継承する新しいプロトタイプオブジェクトを作成しています。すべてのインスタンスがメソッドを共有し、プロトタイプチェーンまでのメソッドを共有します(Baseを含む)。

ChildFactory = Child.constructor;

newキーワードだけコンストラクタ関数上で動作していないプロトタイプは、私たちは基本的に「コンストラクタ関数の変数に、当社のプロトタイプオブジェクト変数を切り替える」と言う必要があるオブジェクト

個人的には「クラスを構築「プロトタイプオブジェクトは実際には直接扱うのが楽しく、インスタンスを作成するときにはコンストラクターの機能が使い勝手が良いとわかりました。我々はvar c = new Child(41);

を呼び出すとき

さてそれから、ベースのコンストラクタを呼び出し、thingsをインクリメントします、我々は定義されたコンストラクタ関数を呼び出します。この時点で

注Cのプロトタイプチェーンを使用すると、プロトタイプに割り当てた場合、それはあなたがそれを完全に上書きすることを意味するものではありません

c -> ([[Prototype]] = Child) 
    -> ([[Prototype]] = Base) 
    -> ([[Prototype]] = Object.prototype) 
    -> null 
+0

ありがとう!これは魅力のように機能します...私はこれについて何かを読んで、何が舞台裏で起こっているか見る必要があります。継承を正しく行う方法については、ネット上に非常に多くの異なる例があります。それらはすべて、ハードビットを避けるためにパラメータのないコンストラクタを持つようです:) – Paul

3

あなたはまったく同じオブジェクト(「BaseClass.prototype」)、および、それには「CHILD2を」「コンストラクタ」プロパティを設定するには、両方のあなたのクラスのプロトタイプを設定しました。言い換えれば、 "Child1.prototype"と "Child2.prototype"は同じなので、あなたのコードに含まれる "constructor"プロパティは1つしかなく、 "Child2"になります。

これらのプロトタイプをインスタンスのBaseClassのに設定したいのですか?

Child1.prototype = new BaseClass(); 
Child1.prototype.constructor = Child1; 

Child2.prototype = new BaseClass(); // a different object 
Child2.prototype.constructor = Child2; 

(@Raynosは、あなたが彼の答えでのアプローチを使用したほうがよい場合もありますので、そのようにプロトタイプ値をインスタンス化することは、微妙な問題を引き起こす可能性があることを指摘している。)

+0

あなたは本当に '.prototype =新しいXを避ける必要があります()'初期化したいいけない 'Xのインスタンスとして.prototype'、あなただけインスタンス化します。 (すなわち、コンストラクタを呼び出すことはありません!) – Raynos

+0

あなたの基底クラスのコンストラクタに引数があるとどうなります - あなたは右クリックし、そこにそれらを初期化する必要がありますか?私の実際の子クラスコードはBaseClass.call(this、 'argument1'、 'argument2')を呼び出しています。そのコンストラクタで。 – Paul

+0

OK @Raynosはい、そうかもしれません。私はそのような問題に対処するために頻繁にそのようなことをしません:-)私はnotを追加します。 – Pointy

1

これは、オブジェクトnew Child1()が「CHILD1」コンストラクタによって作成されたかどうかのチェックを意味するものではありません。 (new Child1()).[[Prototype]]をし、「Child1.prototype」から審査を主演、プロトタイプチェーン内にその存在をチェック - instanceof演算子は、オブジェクトのプロトタイプを取ります。演算子instanceofは、コンストラクタの内部[[HasInstance]]メソッドを介してアクティブ化されます。 だからあなたは次のようにコードを変更する必要があります。http:/

function BaseClass(){} 
function Child1(){} 

Child1.prototype = new BaseClass(); 
Child1.prototype.constructor = Child1; 

function Child2(){} 
Child2.prototype = new BaseClass(); 
Child2.prototype.constructor = Child2; 
console.log((new Child1() instanceof Child2)); // false 

そして、それはjavascriptの

関連する問題