2013-06-27 12 views
5

Der instanceof Operator am Prototyp aussehen sollte, nicht wahr? Warum ändert sich die Antwort nicht, nachdem der Prototyp des Objekts geändert wurde? Beispiel unten:warum instanceof immer wahr sagt, nachdem der Prototyp geändert wurde?

// The .prototype of objects created with 'new MyKlass' 
// is MyKlass.prototype 
var MyKlass = function(name, age) { 
    this.name = name; 
    this.age = age; 
} 

var xx = new MyKlass('xx', 20); 
console.log(xx instanceof MyKlass);  // true, OK 

xx.prototype = new String('s'); 
console.log(xx instanceof MyKlass);  // also true, WHY??? 

Antwort

9

Dieser Fall ist in the MDN erklärt:

Beachten Sie, dass, wenn der Wert eines instanceof-Test kann auf Änderungen an der Eigenschaft prototype der Konstrukteurs-Basis ändern, es nicht geändert werden kann durch ein Objekt Prototyp ändert, weil Ändern einen Objekt Prototyp nicht möglich in Standard ECMAScript ist. Es ist jedoch möglich, die Nicht-Standard-__proto__ pseudo-Eigenschaft mit

Diese falsche würde log:

xx.constructor.prototype = new String('s'); 
console.log(xx instanceof MyKlass); 

Kurz gesagt, Sie sollten nicht versuchen, JavaScript-Objekte zu mutieren, wurden sie nicht darauf ausgelegt, veränderbar sein. Ich weiß nicht, was Ihr Anwendungsfall ist, aber es gibt wahrscheinlich eine bessere Lösung, sei es Zusammensetzung, interner Zustand oder etwas anderes.

+0

zum internen [] [Prototyp] Schreiben Warum kann 'prototype' von' MyKlass' ändern, aber nicht 'xx.prototype'? Arent sowohl "MyKlass" und "xx" Objekte? – zpzp

+0

was meinst du stumm? Kannst du etwas klarer erklären? –

+0

@OliverWatkins ein Objekt zu mutieren, ist der allgemeine Betrieb seine Klasse zu ändern. Die meisten OOP- (oder POOP-) Sprachen lassen das nicht zu, weil es unordentlich ist. –

3

Es sieht nicht an .prototype aber [[Prototyp]], oder das, was in einigen Browsern als .__proto__

xx.__proto__ = new String("s"); 
console.log(xx instanceof MyKlass); 
//false 
console.log(xx instanceof String); 
//true 

Zuweisen eine .prototype Eigenschaft zu einer nicht-Funktion hat, außer der normalen Zuordnung irgend keine Wirkung vorhanden ist normale Eigenschaft wirklich. Und für Funktionen, die nur einen Effekt hat, wenn die Funktion in instanceof Prüfung verwendet wird oder mit new genannt.

+0

hat Einstellung '__proto__' Standard-ECMAScript parallel (vielleicht in ES5)? – zpzp

+0

@zpzp nein, aber es scheint, dass es in ES6 verfügbar sein wird https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto – Esailija

3

Der instanceof-Operator sollte sich den Prototyp ansehen, nein?

Ja, es tut. Siehe die MDN docs.

Warum ändert sich die Antwort nicht, nachdem der Prototyp des Objekts geändert wurde?

var xx = new MyKlass('xx', 20); 
xx.prototype = new String('s'); 

Weil Sie nicht den Prototyp Ihrer xx Objekt geändert haben, aber es gab eine prototype Eigenschaft. Object.getPrototypeOf(xx) === MyKlass.prototype gilt weiterhin. Einzelheiten finden Sie unter __proto__ VS. prototype in JavaScript. Was funktionieren würde:

MyKlass.prototype = {}; // overwrite with a different object 
console.log(xx instanceof MyKlass); // false now, xx doesn't inherit from the {} 

oder

xx.__proto__ = String.prototype; // or something 
console.log(xx instanceof MyKlass); // false now, xx doesn't inherit from MyKlass.prototype 

Beachten Sie, dass über __proto__ in ES5 Nicht-Standard ist

+0

Also die '. Prototype 'Eigenschaft von Funktionen sind in gewisser Weise etwas Besonderes, weil die Einstellung über die Einstellung der Eigenschaft hinaus Bedeutung hat? – zpzp

+0

Ja, es bezieht sich auf das Objekt, von dem Instanzen oder das Vererben abgeleitet werden, wenn die [Funktion als Konstruktor mit 'new' aufgerufen wird (https://developer.mozilla.org/en-US/docs/Web/JavaScript/). Referenz/Betreiber/neu) – Bergi

Verwandte Themen