为什么 Set 的原型方法在 Object.create(Set.prototype) 上调用时会抛出错误
Why does the prototype methods of Set throw an error when called on Object.create(Set.prototype)
*Chrome 控制台:*
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
这真是令人困惑。
let a = Object.create(Set.prototype);
Object.create()
方法创建一个具有指定原型对象和属性的新对象。
在我们的例子中,Object.create()
创建了一个new Set()
的新对象,它将继承Set实例的所有属性和方法。
Set 对象允许您存储任何类型的唯一值,无论是原始值还是对象引用。
在参数的帮助下Set.prototype
您可以使用构造函数的原型对象向所有 Set 实例添加属性或方法。
a instanceof Set
它确认实例 a
是 Set
对象的实例,在我们的例子中是的。
a.add(1);
a
对象没有方法 add()
你调用的方法没有实现
Set.prototype.add() or
a.add()
在这两种情况下,您可以尝试通过对象实例 a
调用 add()
方法,而 a
对象没有 add()
方法。
add()
方法与 Set
Class.
有关
var oSet = new Set();
var CustomSet = Object.create(oSet);
console.log(CustomSet.__proto__.add(10));
当您在控制台中 运行 以上代码时,您会看到它会在集合中推送值 10。
__proto__
是查找链中用于解析方法等的实际对象。
prototype 是当你用 new
创建对象时用来构建 __proto__
的对象
因此原型在实例本身(或其他对象)上不可用,而仅在构造函数上可用。
简而言之:你不能这样做,因为规范说你不能。
参见 Set.prototype.add 的第 3 步:
If S does not have a [[SetData]] internal slot, throw a TypeError exception.
此限制的原因是 Set
方法需要它们正在操作的对象中的特定内部状态。拥有正确的原型是不够的;您还必须为您的对象调用 Set
构造函数,这将创建这些内部字段。
我猜你想做的是 class 内置 Set
。正如规范还指出的那样,使用 ES6 class 语法很容易实现:
class MySet extends Set {}
var s = new MySet();
s.add(1);
另见这个问题:Inheriting from Set.prototype。
*Chrome 控制台:*
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
这真是令人困惑。
let a = Object.create(Set.prototype);
Object.create()
方法创建一个具有指定原型对象和属性的新对象。
在我们的例子中,Object.create()
创建了一个new Set()
的新对象,它将继承Set实例的所有属性和方法。
Set 对象允许您存储任何类型的唯一值,无论是原始值还是对象引用。
在参数的帮助下Set.prototype
您可以使用构造函数的原型对象向所有 Set 实例添加属性或方法。
a instanceof Set
它确认实例 a
是 Set
对象的实例,在我们的例子中是的。
a.add(1);
a
对象没有方法 add()
你调用的方法没有实现
Set.prototype.add() or
a.add()
在这两种情况下,您可以尝试通过对象实例 a
调用 add()
方法,而 a
对象没有 add()
方法。
add()
方法与 Set
Class.
var oSet = new Set();
var CustomSet = Object.create(oSet);
console.log(CustomSet.__proto__.add(10));
当您在控制台中 运行 以上代码时,您会看到它会在集合中推送值 10。
__proto__
是查找链中用于解析方法等的实际对象。
prototype 是当你用 new
__proto__
的对象
因此原型在实例本身(或其他对象)上不可用,而仅在构造函数上可用。
简而言之:你不能这样做,因为规范说你不能。
参见 Set.prototype.add 的第 3 步:
If S does not have a [[SetData]] internal slot, throw a TypeError exception.
此限制的原因是 Set
方法需要它们正在操作的对象中的特定内部状态。拥有正确的原型是不够的;您还必须为您的对象调用 Set
构造函数,这将创建这些内部字段。
我猜你想做的是 class 内置 Set
。正如规范还指出的那样,使用 ES6 class 语法很容易实现:
class MySet extends Set {}
var s = new MySet();
s.add(1);
另见这个问题:Inheriting from Set.prototype。