Skip to content
Advertisement

Javascript prototype inheritance and “instanceof”

I just cannot understand, why in object inheritance “instanceof” fails to evaluate “children”-objects as instances of parent prototypes. For example:

function Parent(property) {
    this.property = property;
}

function Child(property) {
    Parent.call(property);
}

const child = new Child("");

console.log(child instanceof Child); // of course, true
console.log(child instanceof Parent); // false. But why???

As for inheritance of classes (or rather of what is deemed to be classes in JS), the situation is different:

class Parent {
    constructor(property) {
        this.property = property;
    }
}

class Child extends Parent {
    constructor(property) {
        super(property);
    }
}

const child = new Child("");

console.log(child instanceof Child); // true
console.log(child instanceof Parent); // also true!!!

What is the cause of this difference? Is it possible to create children-objects so that they were correctly recognised as instances of their parent prototypes (without resorting to classes)?

Advertisement

Answer

Your first example is, quite simply, not remotely close to how “prototypal inheritance” works in Javascript.

For one thing, Parent.call(property) surely isn’t what you meant. This calls Parent with its this set to property, and no arguments passed, which definitely isn’t what you want. I suspect you mean Parent.call(this, property) – which calls Parent with the same this as is passed to Child, and passing through the property argument. But this isn’t anything to do with “inheritance”.

The instanceof operator simply checks an object’s “prototype chain” to see if the relevant object (the prototype property of the “class” you’re testing against) appears anywhere. The only way to manipulate objects to affect the instanceof operator is to alter the prototype chain.

There are a number of ways to do this, but the standard way to “fake” something like class-based inheritance in JS, pre-ES6, would have been like this:

function Parent(property) {
    this.property = property;
}

function Child(property) {
}

Child.prototype = Object.create(Parent.prototype);

const child = new Child("");

console.log(child instanceof Child);
console.log(child instanceof Parent);

which manually makes all objects constructed from Child delegate to Object.create(Parent.prototype), which itself is an object (one otherwise completely empty and with no special properties) that “inherits” from Parent.prototype. So now when instanceof checks the prototype chain, it finds what it’s looking for, and therefore returns true, as you can see from the above snippet.

Of course, if you really do want class-based inheritance in JS (which I personally wouldn’t recommend, but is certainly popular), the ES6 class syntax gives a much nicer syntactic sugar so you don’t have to manually mess with the prototype chain as above. But be aware that that’s essentially what’s going on “under the hood” with ES6 classes.

I strongly recommend this book (freely available to read online) for much deeper explanations of all this. Chapter 5 is the most relevant one in this context.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement