继承自 Set.prototype

2022-01-17 00:00:00 inheritance set javascript ecmascript-6

这真的让我很烦.我可以轻松地创建一个继承 Array.prototype 方法的新类:

var MyArray = function() {};MyArray.prototype = Array.prototype;var myArray = new MyArray();myArray.push(1);//这是允许的

同样的继承模式似乎不适用于 Set.prototype:

var MySet = function() {};MySet.prototype = Set.prototype;var mySet = new MySet();mySet.add(1);//TypeError: 方法 Set.prototype.add 在不兼容的接收器上调用

这是一个实施问题吗?是否有另一种可以工作的继承模式?我已经在节点 v0.12 和 Canary 中尝试过,结果相同.

这个解决方案有效,但我仍然不确定为什么上面的工作不一样:

var MySet = function(array) {var inst = new Set(array);inst.__proto__ = MySet.prototype;返回机构;}MySet.prototype = Object.create(Set.prototype);

解决方案

这是一个实施问题吗?是否有另一种继承模式可行?

不,按照规范,这种行为是正确的.Set 方法必须在实际集合(使用集合特定的内部槽初始化的对象)上调用,并且不像 Array 方法(基本上适用于所有具有.length 属性).

正如规范声明:p><块引用>

Set 构造函数被设计为可子类化.它可以用来作为 class 定义的 extends 子句中的值.子类打算继承指定 Set 行为的构造函数必须包括对 Set 构造函数的 super 调用以创建和用必要的内部状态初始化子类实例支持 Set.prototype 内置方法.

所以你将不得不使用 ES6 类语法来继承内置函数.

class MySet extends Set {}//默认构造函数有 super() 调用var mySet = new MySet();mySet.add(1);

是否支持这种子类化取决于实现,并非所有运行时和转译器都符合 ES6.

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);

解决方案

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.

相关文章