5

コンストラクター関数にプロトタイプが設定されている場合、オペレーターはプロトタイプが変更されるまでのinstanceofみ戻ります。trueなんで?

function SomeConstructorFunction() {
}

function extendAndInstantiate(constructorFn) {
    constructorFn.prototype = {}; //Can be any prototype
    return new constructorFn();
}

var child1 = extendAndInstantiate(SomeConstructorFunction);
console.log(child1 instanceof SomeConstructorFunction); //true

var child2 = extendAndInstantiate(SomeConstructorFunction);
console.log(child1 instanceof SomeConstructorFunction); //false
console.log(child2 instanceof SomeConstructorFunction); //true
4

4 に答える 4

3
constructorFn.prototype = {}; //Can be any prototype

違います!

constructorFn.prototype = Object.prototype;

または、他のネイティブプロトタイプを使用すると、すべてが真になります。

その理由は、初めて呼び出すときにextendAndInstantiate()、SomeConstructorFunctionのプロトタイプを何か(ここでは空のオブジェクト{})に設定しているためです。の場合child1、instanceOfはtrueを返すだけですが、SomeConstructorFunctionのプロトタイプは。の正確なインスタンスです{}extendAnInstantiate()2回目の実行では、SomeConstructorFunctionのプロトタイプをの別のインスタンスに変更している{}のでchild2、その新しいのinstanceOfになりますが{}child1それでも古いのinstanceOfである{}ため、trueを返しchild1ながらfalseをchild2返します。Object.prototypeプロトタイプをまたはなどの一般的なプロトタイプに設定するArray.prototypeと、常にtrueが返されます。

これを説明する別の方法{}は、関数を引き出して変数に割り当てることですobj

var obj = {};
function extendAndInstantiate(constructorFn) {
    constructorFn.prototype = obj;
    return new constructorFn();
}

{}関数を実行するたびに新しいものを作成するわけではないため、これは常にtrueを返します。

于 2013-03-19T15:03:02.377 に答える
3

プロトタイプの継承は、ちょっとした頭脳のベンダーになる可能性があります。プロトタイプの継承についての簡単な説明を次の回答ですでに書いています。それを読むことをお勧めします:https ://stackoverflow.com/a/8096017/783743

今あなたの質問に答えるために。次の関数について考えてみます。

function F() {}

次のようにFusingのインスタンスを作成できます。new

var f = new F;

期待どおりf instanceof Fに戻りますtrue。これは、オペレーターがのプロトタイプチェーンをinstanceofチェックし、存在する場合は戻るためです。上記のリンク先の回答を参照してください。F.prototypeftrue

ここで、次のように新しい関数を作成し、G次のように設定F.prototypeするとしG.prototypeます。

function G() {}

F.prototype = G.prototype;

f instanceof Fもう一度評価するfalseと返されます。これは、F.prototypeがのプロトタイプチェーンに含まれなくなったためです(現在はfそうであることを思い出してください)。F.prototypeG.prototype

F次に、 :の新しいインスタンスを作成しましょう。

var g = new F;

評価すると、それでもg instanceof G返されます。これは、のプロトタイプチェーンに存在するためです。trueg = new FG.prototypeg

これはバグではありません。これがJavaScriptの仕組みです。実際、この機能を利用して、いくつかの非常に興味深い関数を作成できます。カスタムプロトタイプを使用してJavaScript関数をインスタンス化する

于 2013-03-19T15:24:08.977 に答える
0

instanceofプロトタイプオブジェクトに基づいています。

function extendAndInstantiate(constructorFn) {
constructorFn.prototype = {}; //Can be any prototype
...

プロトタイプを{}に設定すると、新しいオブジェクトが作成され、プロトタイプとして設定されます。その場合、それはプロトタイプと同じオブジェクトではないため、instanceoffalseを返します。

プロトタイプは同じオブジェクトになるため、このような設定はすべての場合にtrueを返します。

function SomeConstructorFunction() {
}

var emptyObj = {};

function extendAndInstantiate(constructorFn) {
    constructorFn.prototype = emptyObj; 
    return new constructorFn();
}

var child1 = extendAndInstantiate(SomeConstructorFunction);
console.log(child1 instanceof SomeConstructorFunction); //true

var child2 = extendAndInstantiate(SomeConstructorFunction);
console.log(child1 instanceof SomeConstructorFunction); //true
console.log(child2 instanceof SomeConstructorFunction); //true
于 2013-03-19T15:08:48.250 に答える
0

を呼び出すたびにextendAndInstantiate、を使用して新しいオブジェクトが作成{}され、のプロトタイプとして割り当てられSomeConstructorFunctionます。これにより、既存のインスタンスとの間のリンクがクリアされますSomeConstructorFunction。したがって、最後の1つだけがの有効なインスタンスになりますSomeConstructorFunction

function SomeConstructorFunction() {

}

function extendAndInstantiate(constructorFn) {
  constructorFn.prototype = {}; //New instance as prototype
    return new constructorFn();
}

var child1 = extendAndInstantiate(SomeConstructorFunction);
console.log(child1 instanceof SomeConstructorFunction); //true

var child2 = extendAndInstantiate(SomeConstructorFunction);
console.log(child1 instanceof SomeConstructorFunction); //false
console.log(child2 instanceof SomeConstructorFunction); //true


var child3 = extendAndInstantiate(SomeConstructorFunction);
console.log(child1 instanceof SomeConstructorFunction); //false
console.log(child2 instanceof SomeConstructorFunction); //false
console.log(child3 instanceof SomeConstructorFunction); //true

したがって、@ ben336で示されている方法に従うか、以下に示すようにプロトタイプを割り当てる前に条件チェックを行うことができます。

function Base(){

}

function SomeConstructorFunction() {

}

function extendAndInstantiate(constructorFn, Base) {
  if(!(constructorFn.prototype instanceof Base)){
    console.log(" extend only once ");
    constructorFn.prototype = new Base(); 
  }
  return new constructorFn();
}


var child1 = extendAndInstantiate(SomeConstructorFunction, Base);
console.log(child1 instanceof SomeConstructorFunction); //true

var child2 = extendAndInstantiate(SomeConstructorFunction, Base);
console.log(child1 instanceof SomeConstructorFunction); //true
console.log(child2 instanceof SomeConstructorFunction); //true


var child3 = extendAndInstantiate(SomeConstructorFunction, Base);
console.log(child1 instanceof SomeConstructorFunction); //true
console.log(child2 instanceof SomeConstructorFunction); //true
console.log(child3 instanceof SomeConstructorFunction); //true
于 2013-03-19T15:18:12.137 に答える