TypeError: Initializing an object twice is an error with private fields/methods
JavaScript 异常“使用私有字段/方法初始化对象两次是错误”发生在一个通过类构造函数创建的对象再次经历类构造,并且该类包含一个私有元素时。这通常是由返回覆盖技巧引起的。
消息
TypeError: Cannot initialize #x twice on the same object (V8-based) TypeError: Initializing an object twice is an error with private fields (Firefox) TypeError: Cannot redefine existing private field (evaluating 'super(o)') (Safari) TypeError: Cannot initialize private methods of class X twice on the same object (V8-based) TypeError: Initializing an object twice is an error with private methods (Firefox) TypeError: Cannot install same private methods on object more than once (evaluating 'super(o)') (Safari)
错误类型
TypeError
哪里出错了?
对于任何对象,如果它已经包含一个私有字段或方法,那么再次安装相同的字段将是一个错误。私有元素在调用类构造函数时安装在 this 的值上,因此如果 this 值是该类的一个已构造实例,就可能发生此错误。
通常,构造函数中的 this 是一个新创建的对象,它没有任何预先存在的属性。但是,它可以通过基类的返回值来覆盖。如果基类返回另一个对象,该对象将替换当前对象作为 this 的值。
js
class Base {
constructor(o) {
// This object will become the this value of any subclass
return o;
}
}
class Derived extends Base {
#x = 0;
}
如果你调用 new Derived(anyObject),其中 anyObject 不是 Derived 的实例,那么 Derived 构造函数将以 anyObject 作为 this 值被调用,从而在 anyObject 上安装 #x 私有字段。这就是“返回覆盖”技巧,它允许你在不相关的对象上定义任意信息。但是,如果你调用 new Derived(new Derived()),或再次调用 new Derived(anyObject),Derived 构造函数将尝试在一个已经拥有 #x 私有字段的对象上再次安装 #x 私有字段,从而导致此错误。