Javascript: still confused by instanceof operator

This article defines an instance as shown below:

The instanceof operator checks whether the object in its prototype has a property to bind to the constructor prototype property.

This fair explanation and life was good until I came across this code from the book "Eloquent 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; }; 

Let create an instance of RTextCell and execute below c

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

I understand why the output of the second console.log is "true" - because the TextCell constructor is part of the prototype chain.

However, the first .log console confuses me.

If you look at the code (line 10 below), the RTextCell prototype will be updated to a new object whose prototype is set to TextCell.prototype.

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

Looking at the pictures below, the RTextCell constructor is not mentioned in the prototype chain of the rt object. So, based on the definition that I mentioned at the beginning of my post, should the conclusion not be false? Why does it return the true value?

I also read this one , but did not help me understand this particular problem.

Below are snapshots of rt, RTextCell, TextCell in that order.

snapshot of "rt"snapshot of RTextCellsnapshot of TextCell

+5
source share
3 answers

The exact wording is important. You are talking about the constructor in the prototype chain, but the original quote does not:

The instanceof operator checks whether the object in its prototype has a property to bind to the constructor prototype property.

So the rt instanceof RTextCell really tests something like this (bearing in mind that __proto__ not standard):

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

So, although the RTextCell function RTextCell not specified directly in the object trees above, the RTextCell.prototype object is.

+1
source

You change RTextCell.prototype , but you change it before creating any instances of RTextCell . Consider this completely different example where RTextCell.prototype changes after creating an instance with the original prototype:

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

When rt is created, it is true that rt.__proto__ === RTextCell.prototype . When RTextCell.prototype changes, it ceases to be true.

You do not test if rt has the original prototype property from RTextCell in its prototype chain. Rather, you are checking to see if the RTextCell.prototype value RTextCell.prototype in the object prototype chain. This will always be true for RTextCell instances, because instances created by the RTextCell constructor always get the current RTextCell.prototype value in the prototype chain, and you never change RTextCell.prototype after you start creating the instances.

+4
source
 obj instanceof RTextCell 

checks if RTextCell.prototype is present in the obj prototype chain. This is because obj was created using the new RTextCell. The fact that RTextCell.prototype has as prototype TextCell.prototype is next to the dot and seems to throw you.

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

does not get rid of RTextCell.prototype, it is still an object, but the prototype is TextCell.prototype.

+1
source

All Articles