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 私有欄位,從而導致此錯誤。