2013-06-27 18 views
5

L'operatore instanceof dovrebbe guardare il prototipo, no? Perché non cambia la sua risposta dopo che il prototipo dell'oggetto è stato modificato? Esempio di seguito:perché instanceof continua a dire true dopo il prototipo modificato?

// 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??? 

risposta

9

Questo caso è spiegato in the MDN:

Si noti che se il valore di un test instanceof può variare a seconda modifiche alla proprietà prototipo di costruttori, non si può cambiato cambiando un prototipo dell'oggetto, perché la modifica di un prototipo dell'oggetto non è possibile in ECMAScript standard. E 'comunque possibile utilizzare il __proto__ pseudo-proprietà non standard

Questo sarebbe il login falso:

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

In breve, non si dovrebbe cercare di mutare gli oggetti JavaScript, essi non sono stati progettati per essere mutabile Non so qual è il tuo caso d'uso ma probabilmente c'è una soluzione migliore, che si tratti di composizione, stato interno o qualcos'altro.

+0

Perché può 'prototype' di' MyKlass' cambia ma non 'xx.prototype'? Arent entrambi gli oggetti 'MyKlass' e' xx'? – zpzp

+0

cosa intendi per muto? puoi spiegare un po 'meglio? –

+0

@OliverWatkins La mutazione di un oggetto è l'operazione generale di modifica della sua classe. La maggior parte delle lingue OOP (o POOP) non ti consente di farlo perché è disordinato. –

3

Non guardare .prototype ma [[prototype]], o ciò che è disponibile in alcuni browser come .__proto__

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

Assegnazione di un immobile .prototype a un non funzione non ha alcun effetto se non il normale assegnazione di qualsiasi proprietà normale davvero. E per le funzioni che hanno effetto solo quando la funzione è utilizzata nel controllo instanceof o chiamata con new.

+0

l'impostazione di '__proto__' è parallela allo standard ECMAScript (forse in ES 5)? – zpzp

+0

@zpzp no ma sembra che sarà disponibile in ES6 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto – Esailija

3

L'operatore dell'istanza deve guardare il prototipo, no?

Sì, lo fa. Vedi lo MDN docs.

Perché non cambia la sua risposta dopo che il prototipo dell'oggetto è stato modificato?

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

Perché non ha modificato il prototipo del xx oggetto, ma ha dato una proprietà prototype. Object.getPrototypeOf(xx) === MyKlass.prototype ancora valido. Vedi __proto__ VS. prototype in JavaScript per i dettagli. Che cosa avrebbe funzionato:

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

o

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

Si noti che per iscritto al interno [[prototype]] tramite __proto__ è non standard in ES5

+0

Quindi la proprietà '.prototype' di le funzioni sono speciali in un certo senso, perché impostarle ha un significato che va oltre la semplice impostazione della proprietà? – zpzp

+0

Sì, si riferisce all'oggetto che istanze o set ereditano da quando [la funzione viene chiamata come costruttore con 'new'] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/ Riferimento/operatori/nuovo) – Bergi

Problemi correlati