プロトタイプの継承された子クラスが別の子クラスのインスタンスであるのはなぜですか?

おそらく私はこれを間違っていると思います。私は基本クラスとそのクラスを継承する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
JSで継承を使用するさまざまな方法については、以下のリソースを参照してください。 3site.eu/doc
追加された 著者 Cᴏʀʏ,

4 答え

両方のクラスのプロトタイプをまったく同じオブジェクト( "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は、そのようなプロトタイプの値をインスタンス化すると、微妙な問題を引き起こす可能性があることを指摘しているので、彼の答えにアプローチを使用することをお勧めします)。

3
追加された
Xのインスタンスとして .prototype を初期化したくない .prototype = new X()は、インスタンス化したいだけです。 (つまりコンストラクタを呼び出さないでください)
追加された 著者 Raynos,
@ShyGuyあなたはそれらを初期化せず、そこでは、あなたは子供のコンストラクタでそれを行います。
追加された 著者 Raynos,
@Pointy:多くのオブジェクトフレームワークは、汚れたハックであるため "init"を推奨します。継承の際にコンストラクタを使用しないでください(ヒント: Object.create )。
追加された 著者 Raynos,
@Pointyはい、それは誰でもJavaScriptを言うたびに "ES5"と思うというこの悪い癖を持っています。私はそれをオフにすることはできません!
追加された 著者 Raynos,
基本クラスのコンストラクタに引数がある場合はどうなりますか - それをすぐに初期化する必要がありますか?私の実際の子クラスコードはBaseClass.call(this、 'argument1'、 'argument2')を呼び出しています。そのコンストラクタで。
追加された 著者 Paul,
OK @ Raynosはい、そうかもしれません。私はそのような問題に対処するために頻繁にそのようなことをしません:-)私はnotを追加します。
追加された 著者 Pointy,
@ShyGuy私はそれが多くのオブジェクトフレームワークが "init"関数を呼び出すための規約を使用している理由だと思います。
追加された 著者 Pointy,
@ Raynosあなたは確かにこれより多くのことを私よりもよく知っています:-)私はたくさんのJavaScriptを書いていますが、JavaScriptで「object-y」コードを書いていません。 (また、ES5のことは Object.create ではないでしょうか?おそらく、MDNにpolyfillがあります。
追加された 著者 Pointy,

Child1.prototype = BaseClass.prototype;

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

You don't want the prototype object to be the same, you want a new prototype object that inherits from BaseClass

実例

Disclaimer: Object.create is ES5, use the ES5-shim for legacy platform support.

あなたにもっと徹底的な例を与えるために:

// 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 で呼び出すことができる関数である "Constructor関数"をリンクする必要があります。これは基本的にあなたが手作業で行う必要がある接着剤です。なぜなら、ESはこれをあなたのためにしていないからです。

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

var Child = Object.create(Base);

[[Prototype]]Base の新しいオブジェクトを作成します。これは基本的にプロトタイプチェーンの始まりです

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

Child.x = ...

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

ChildFactory = Child.constructor;

new キーワードは、プロトタイプオブジェクトではなくコンストラクタ関数でのみ機能するので、基本的には「プロトタイプオブジェクト変数をコンストラクタ関数変数に切り替える」必要があります

個人的には、「クラス」を構築するときには、プロトタイプオブジェクトが直接扱うのが楽しく、インスタンスを作成するときには、コンストラクターが扱うのが楽しいことがわかります。

Now when we call var c = new Child(41);

things をインクリメントして定義したコンストラクタ関数を呼び出し、基本コンストラクタを呼び出します。

この時点で、cのプロトタイプチェーンは次のようになります

c -> ([[Prototype]] = Child) 
  -> ([[Prototype]] = Base) 
  -> ([[Prototype]] = Object.prototype) 
  -> null
2
追加された
ありがとう!これは魅力のように機能します...私はこれについて何かを読んで、何が舞台裏で起こっているか見る必要があります。継承を正しく行う方法については、ネット上に非常に多くの異なる例があります。それらはすべて、ハードビットを避けるためにパラメータのないコンストラクタを持つようです:)
追加された 著者 Paul,

これは、 new Child1()オブジェクトが "Child1"コンストラクタによって作成されているかどうかのチェックではありません。 instanceof 演算子は、オブジェクトプロトタイプ(new Child1())[[Prototype]] のみを取り、プロトタイプチェーンでのその存在をチェックし、 。プロトタイプ"。演算子 instanceof は、コンストラクタの内部[[HasInstance]]メソッドを介してアクティブ化されます。 したがって、次のようにコードを変更する必要があります。

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でOOPの正しい実装になります

1
追加された

プロトタイプに割り当てると、それを完全に上書きするという意味ではありませんか?したがってChild1とChild2は実際には子クラスではなくBaseClassオブジェクトになります。

http://www.zipcon.net/~swhiteも参照してください。 /docs/computers/languages/object_oriented_JS/inheritance.html JSの適切なオブジェクト指向はかなりの労力を要する。

1
追加された
JavaScript - 日本のコミュニティ
JavaScript - 日本のコミュニティ
2 参加者の

日本人コミュニティのjavascript