[英]JavaScript subclass method called by parent constructor transiently setting instance properties
我試圖在 JavaScript 中做一些父/子樣式繼承並遇到一些意外行為:
class Dad { constructor() { this.init(); } init() {} } class Son extends Dad { foo; init() { this.foo = 'bar'; console.log('init', this.foo); } } let son = new Son(); console.log('son', son.foo);
預計 output:
init bar
son bar
實際 output:
init bar
son undefined
為什么 son.bar 在son.init()
被調用和父構造函數返回新的 object 之間被取消設置?
所以顯然這是一個操作順序問題。
執行順序:
Son
隱含的構造函數被調用super()
或Dad constructor
Son.init()
被稱為this.foo
設置為'bar'
( Dad
構造函數完成)super()
構造函數完成后,子Son
class 顯然將Son
class scope 中定義的屬性設置為其默認值,在本例中為foo;
或foo = undefined;
我不喜歡它,但一種解決方案是刪除foo;
來自Son
class 的定義。 顯然 VS Code intellisense 仍然會選擇foo
屬性,即使它沒有在 class 定義或構造函數中定義,這是目標之一。 就可讀性而言,在 class 定義或構造函數中不包含foo
會稍差一些。
另一個解決方案:
class Dad { // To be called after super() in child constructors // Class field initializers overwrite assignments made by super(), so // anything set here could be overwritten if it were in the constructor callMeAfterSuper() { this.init(); } init() {} } class Son extends Dad { foo; constructor() { super(); super.callMeAfterSuper(); } init() { this.foo = 'bar'; console.log('init', this.foo); } } let son = new Son(); console.log('son', son.foo);
尋址JavaScript 父構造函數瞬時設置實例屬性調用的子類方法:
另一種與孫輩兼容但更不優雅的方法:
class Dad {
// To be called after super() in child constructors
// Class field initializers overwrite assignments made by super(), so
// anything set here could be overwritten if it were in the constructor
callMeAfterSuper() {
this.init();
}
init() { }
}
class Son extends Dad {
foo;
constructor() {
super();
if( this.constructor.name === Son.name ) super.callMeAfterSuper();
}
init() {
super.init();
this.foo = 'bar';
}
}
class Grandson extends Son {
littleFoo;
constructor() {
super();
if( this.constructor.name === Grandson.name ) super.callMeAfterSuper();
}
init() {
super.init();
this.littleFoo = 'littleBar';
}
}
let son = new Grandson();
console.log('son', son.foo, son.littleFoo);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.