簡體   English   中英

JavaScript 父構造函數調用的子類方法瞬時設置實例屬性

[英]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 之間被取消設置?

所以顯然這是一個操作順序問題。

執行順序:

  1. Son隱含的構造函數被調用
  2. ...調用super()Dad constructor
  3. Son.init()被稱為
  4. this.foo設置為'bar'Dad構造函數完成)
  5. 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM