Search code examples
javascriptecmascript-6javascript-inheritance

ES6 Class extending native type makes instanceof behave unexpectedly in some JavaScript engines?


Consider the following ES6 Classes:

'use strict';

class Dummy {
}

class ExtendDummy extends Dummy {
    constructor(...args) {
        super(...args)
    }
}

class ExtendString extends String {
    constructor(...args) {
        super(...args)
    }
}

const ed = new ExtendDummy('dummy');
const es = new ExtendString('string');

console.log(ed instanceof ExtendDummy);
console.log(es instanceof ExtendString);

My understanding is that both should be true, and in Firefox and Chrome they are, however Node says es instanceof ExtendString is false. It's the same with other constructors, not just String.

Software I used:

  • Node v5.11.0 with the --harmony flag.
  • Chrome 50
  • Firefox 45

Which JavaScript engine is correct and why?


Solution

  • Node appears to be incorrect, es instanceof ExtendString should definitely be true (like everyone would expect).

    String[Symbol.hasInstance] is not overwritten, and Object.getPrototypeOf(es) should be ExtendedString.prototype, as the spec details this in the String (value) function description:

    1. Return StringCreate(s, GetPrototypeFromConstructor(NewTarget, "%StringPrototype%")).

    The newtarget refers to ExtendString when you construct the new ExtendString('string') instance, and since it is a constructor with a .prototype object it will use ExtendedString.prototype not %StringPrototype as the [[prototype]] for the newly created exotic String object:

    1. Set the [[Prototype]] internal slot of S to prototype.