2015-05-22 28 views
5

Questo article definisce instanceof come qui sotto:JavaScript: Ancora confuso dall'operatore instanceof

test operatore

instanceof se un oggetto ha nella sua catena di prototipi proprietà prototipo di un costruttore.

Questa è una spiegazione giusta e la vita è stata buona fino a quando mi sono imbattuto in questo codice dal libro eloquente Javascript:

function TextCell(text) { 
 
    this.text = text.split("\n"); 
 
} 
 

 
TextCell.prototype.minWidth = function() { 
 
    return this.text.reduce(function(width, line) { 
 
    return Math.max(width, line.length); 
 
    }, 0); 
 
} 
 

 
TextCell.prototype.minHeight = function() { 
 
    return this.text.length; 
 
} 
 

 
TextCell.prototype.draw = function(width, height) { 
 
    var result = []; 
 
    for (var i = 0; i < height; i++) { 
 
    var line = this.text[i] || ""; 
 
    result.push(line + repeat(" ", width - line.length)); 
 
    } 
 
    return result; 
 
} 
 

 
function RTextCell(text) { 
 
    TextCell.call(this, text); 
 
} 
 

 
RTextCell.prototype = Object.create(TextCell.prototype); 
 

 
RTextCell.prototype.draw = function(width, height) { 
 
    var result = []; 
 
    for (var i = 0; i < height; i++) { 
 
    var line = this.text[i] || ""; 
 
    result.push(repeat(" ", width - line.length) + line); 
 
    } 
 
    return result; 
 
};

Creiamo un'istanza di RTextCell ed eseguire il sotto c

var rt = new RTextCell("ABC"); 
console.log(rt instanceof RTextCell); // true 
console.log(rt instanceof TextCell); // true 

Capisco perché l'output del 2 ° console.log è "true" - perché il costruttore TextCell fa parte della catena del prototipo.

Tuttavia il 1 ° console.log mi confonde.

Se si guarda il codice (decima riga dal basso), il prototipo di RTextCell viene aggiornato a un nuovo oggetto, il cui prototipo è impostato su TextCell.prototype.

RTextCell.prototype = Object.create(TextCell.prototype);.

Guardando le istantanee di seguito, non si fa menzione del costruttore "RTextCell" nella catena di prototipi dell'oggetto "rt". Quindi, seguendo la definizione che ho menzionato all'inizio del mio post, l'output non dovrebbe essere falso? Perché restituisce un valore vero?

Ho letto anche this ma non mi ha aiutato a capire questo problema specifico.

Vedere di seguito le istantanee di rt, RTextCell, TextCell in questo ordine.

snapshot of "rt" snapshot of RTextCell snapshot of TextCell

+0

È una domanda davvero ben strutturata. Hai mostrato tutte le tue indagini precedenti, spero che tu ottenga ottime risposte. –

+0

Oh! Dovrei aggiungere Ho controllato questo prototipo di catena nelle istantanee di cui sopra sia su Chrome 43.0.2357.65 che su Firefox 33.1.1. – Harish

risposta

1

La dicitura esatta è importante. Si parla di costruttore essendo nella catena di prototipi, ma la citazione originale non:

instanceof test operatore se un oggetto ha nella sua catena di prototipi la proprietà prototipo di un costruttore.

Quindi l'espressione rt instanceof RTextCell in realtà sta testando qualcosa di simile (tenendo presente che __proto__ non è standard):

var p = rt.__proto__; 
while(p) 
{ 
    if(p == RTextCell.prototype) 
    return true; 
    p = p.__proto__; 
} 
return false; 

Così, anche se la funzione RTextCell non fa riferimento direttamente tra gli alberi di oggetti di cui sopra, l'oggetto RTextCell.prototype è.

+0

o in una singola espressione, 'RTextCell.prototype.isPrototypeOf (rt)' :-) – Bergi

+0

@Dark Falcon: In precedenza ero confuso dall'operatore instanceof e isPrototypeOf() e quando ho visto la parola "costruttore" in definizione su Sito MDN ho totalmente frainteso. La tua risposta mi ha fatto sospendere per un secondo e rendermi conto di ciò che mi mancava. "La formulazione". Ora ha senso. E ho anche appena letto [questo]. (Http://stackoverflow.com/questions/18343545/javascript-isprototypeof-vs-instanceof-usage) per la differenza tra instanceof e isPrototypeOf(). Grazie compagno. – Harish

1
obj instanceof RTextCell 

sta testando se RTextCell.prototype è presente nella catena di prototipi obj. È da quando è stato creato obj con il nuovo RTextCell. Il fatto che RTextCell.prototype abbia come prototipo TextCell.prototype è qui accanto e sembra che ti stia lanciando.

RTextCell.prototype = Object.create(TextCell.prototype); 

non sbarazzarsi di RTextCell.prototype, è ancora un oggetto, ma è il prototipo sembra essere TextCell.prototype.

4

si modifica RTextCell.prototype, ma si cambia prima si costruisce qualsiasi RTextCell istanze. Considerate questo esempio massicciamente diverso, dove RTextCell.prototype viene modificato dopo che l'istanza viene creato con il prototipo originale:

var rt = new RTextCell(); 
RTextCell.prototype = somethingTotallyDifferent; 
rt instanceof RTextCell; // false! 

Quando si crea rt, è vero che rt.__proto__ === RTextCell.prototype. Dopo le modifiche RTextCell.prototype, non è più possibile.

Non stai testando se rt ha l'originaleprototype proprietà da RTextCell nella sua catena di prototipi. Piuttosto, stai verificando se il valore di RTextCell.prototypeal momento esiste nella catena di prototipi dell'oggetto. Ciò sarà sempre vero per le istanze RTextCell, poiché le istanze create dal costruttore RTextCell ottengono sempre il valore corrente di RTextCell.prototype nella loro catena di prototipi e non si modifica mai RTextCell.prototype dopo aver iniziato a costruire istanze.

+0

Oltre alla risposta di @Dark Falcon, il tuo esempio sull'impostazione del prototipo su "qualcosa di totalmente diverso" mi ha aiutato. Questo ha senso. Grazie. – Harish