簡體   English   中英

ES6,由父級的構造函數訪問子級設置的道具

[英]ES6, access props set by the child from the parent's constructor

我試圖用ES6類建立一個類層次結構。

所有實體都將從單個Base類繼承。 它需要以通用方式訪問Child類公開的屬性。 像這樣:

class Base {
    constructor() {
        this.doSomethingWithProps();
    }

    doSomethingWithProps() {
        console.log(Object.keys(this));
    }
}

class Entity extends Base {
    constructor() {
        super();

        this.key = "value";
    }
}

顯然,在上面的示例中, Base類將看不到Entity設置的key道具。 理想情況下,我this分配移到super()之前,但這是不允許的。 能夠在構造函數之前設置屬性也很好,但是AFAIK也是不可能的。

我剩下的唯一解決方案是在每個Entity執行以下操作:

class Base {
    doSomethingWithProps() {
        console.log(Object.keys(this));
    }
}

class Entity extends Base {
    constructor() {
        super();

        this.key = "value";

        this.doSomethingWithProps();
    }
}

但是,除了不盡如人意之外,如果我隨后想從Entity繼承,也會造成問題。 然后, doSomethingWithProps將需要能夠檢測它是否是調用層次結構中的“最頂層”方法,然后才執行其操作。 實現這一目標 (我能想到)的唯一方法將涉及更多樣板。

有什么解決方案我想念嗎? 我願意在需要時使用其他OOP模式,盡管我希望盡可能與本機ES6類保持聯系。

您試圖做的事情是完全不可能的。 父級初始化始終在子級初始化之前運行,因此,父級構造函數必須不依賴於可能會被子級覆蓋的屬性。 順便說一句,這是一個與語言無關的問題。

解決方案是使用構造函數的參數,這些參數可以在到達父代碼之前在子代中進行修改:

class Base {
    constructor(key) {
        this.key = key;
        // do something with key
    }
}

class Entity extends Base {
    constructor() {
        super("value");
    }
}

console.log(new Entity);

或更通用

class Base {
    constructor(props) {
        this.doSomething(props);
        Object.assign(this, props);
    }

    doSomething(props) {
        return Object.keys(props);
    }
}

class Entity extends Base {
    constructor() {
        super({key: "value"});
    }
}

console.log(new Entity);

還要注意,構造函數應始終是純凈的。 它們的唯一目的是從參數初始化新實例,並且不執行其他任何副作用。 構造函數通常不需要調用任何(可重寫)實例方法(盡管可以使用靜態方法)。
因此,如果在創建實例時仍然需要執行類似的操作,則不要在構造函數中執行此操作。 而是在使用構造函數后調用方法:

class Base {
    log() {
        console.log(Object.keys(this));
        return this;
    }
}

class Entity extends Base {
    constructor() {
        super();
        this.key = "value";
    }
}

var e = new Entity().log();

您還可以將其抽象出來:

class Base {
    static createAndLog(...args) {
        var x = new this(...args);
        x.log();
        return x;
    }
    …
}
…

var e = Entity.createAndLog();

根據您要走的復雜程度,可能有兩條路線可以走。

1.保持狀態在Base

如果可能,將所需的道具從Entity傳遞到Base並在其中維護狀態。

 class Base { constructor(props) { for (var k in props) { this[k] = props[k] } this.doSomethingWithProps(); } doSomethingWithProps() { console.log(Object.keys(this)); } } class Entity extends Base { constructor(props) { super(props); } } let entity = new Entity({key: 'value'}) // ["key"] 

2.將對Entity引用傳遞給Base

注意,我錯誤地假設了Entity ..的單獨實例。這過於冗余。

不是那么簡單,並且從技術上講將包含一個自引用鍵,因為Entity將從Base繼承child鍵。 絕對可以認為這是一種“錯誤”的方法,但是我將其包括在內。

 class Base { constructor() { this.child } registerChild(child) { this.child = child this.doSomethingWithProps() } doSomethingWithProps() { console.log(Object.keys(this.child)); } } class Entity extends Base { constructor() { super(); this.key = 'value' this.registerChild(this) } } let entity = new Entity() // ["key", "child"] 

我認為這里的觀察應該是:避免在構造函數中調用依賴於對象狀態的方法,因為構造函數旨在構建該狀態。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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