Search code examples
javascriptecmascript-6setprototypev8

Why does the prototype methods of Set throw an error when called on Object.create(Set.prototype)


*Chrome console:*

let a = Object.create(Set.prototype);
a instanceof Set    // true
a.add(1);    // Uncaught TypeError: Method Set.prototype.add called on incompatible receiver #<Set>
Set.prototype.add.call(a);    // the same as above

This is really confusing.


Solution

  • In short: you can't do this because the specification says you can't.

    See step 3 of Set.prototype.add:

    If S does not have a [[SetData]] internal slot, throw a TypeError exception.

    The reason for this restriction is that the Set methods require certain internal state in the object they are operating on. Having the right prototype is not enough; you must also call the Set constructor for your objects, which will create those internal fields.

    I guess what you're trying to do is to subclass the built-in Set. As the spec also points out, that is easily possible using ES6 class syntax:

    class MySet extends Set {}
    var s = new MySet();
    s.add(1);
    

    See also this question: Inheriting from Set.prototype.