Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheriting from Set.prototype

This is really bugging me. I can easily create a new class that inherits methods from Array.prototype:

var MyArray = function() {};

MyArray.prototype = Array.prototype;

var myArray = new MyArray();
myArray.push(1); // this is allowed

The same inheritance pattern doesn't seem to work with Set.prototype:

var MySet = function() {};

MySet.prototype = Set.prototype;

var mySet = new MySet();
mySet.add(1); // TypeError: Method Set.prototype.add called on incompatible receiver

Is this an implementation issue? Is there another inheritance pattern that will work? I've tried this in node v0.12 and Canary with the same results.

EDIT: This solution works, but I'm still not sure why the above doesn't work the same:

var MySet = function(array) {
  var inst = new Set(array);
  inst.__proto__ = MySet.prototype;
  return inst;
}

MySet.prototype = Object.create(Set.prototype);
like image 876
djfdev Avatar asked Sep 29 '22 05:09

djfdev


1 Answers

Is this an implementation issue? Is there another inheritance pattern that will work?

No, this behaviour is correct as by the spec. The Set methods must be invoked on actual sets (objects initialised with set-specific internal slots), and are not generic as the Array methods (which basically work on everything that has a .length property).

As the spec states:

The Set constructor is designed to be subclassable. It may be used as the value in an extends clause of a class definition. Subclass constructors that intend to inherit the specified Set behaviour must include a super call to the Set constructor to create and initialize the subclass instance with the internal state necessary to support the Set.prototype built-in methods.

So you will have to use ES6 class syntax to inherit from the built-ins.

class MySet extends Set {} // default constructor has super() call

var mySet = new MySet();
mySet.add(1);

Whether this subclassing is supported depends on the implementation, not all runtimes and transpilers are ES6-compliant yet.

like image 114
Bergi Avatar answered Oct 03 '22 02:10

Bergi