# derived class init

<img src="https://2527454625-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MfvEFZnSBhKT6fJmus0%2Fuploads%2FqqRD2ltCjQ9vzd5GOWqN%2Ffile.drawing.svg?alt=media&#x26;token=f76c240d-9d70-403a-8926-0f4f4b43310b" alt="derived class initialization" class="gitbook-drawing">

{% tabs %}
{% tab title="💾 程式" %}
{% hint style="danger" %}
在初始化的過程中，因為 **parent class** 的 **class fields** 會先初始化、**constructor** 會先執行，所以如果此時在 <mark style="color:orange;">**parent constructor**</mark> 內提及 <mark style="color:purple;">**this**</mark> 物件的 <mark style="color:red;">**overridden class fields**</mark> 的話，由於這時的 <mark style="color:yellow;">**overridden class fields**</mark> <mark style="color:red;">**尚未完全初始化**</mark>，因此可能會產生「**輸出錯誤(未成熟)的屬性**」的問題❗️

👉 詳情請看： [override-class-fields](override-class-fields "mention")「❗狀況 」頁面
{% endhint %}

{% hint style="warning" %}
⭐️ Note: when "<mark style="color:orange;">**parent constructor**</mark>" is called (in an initialization process):

* "<mark style="color:red;">**overridden methods**</mark>" are used ❗
* "<mark style="color:yellow;">**parent class fields**</mark>" are used ❗❗
{% endhint %}

{% hint style="success" %}
也就是說：如果在 <mark style="color:orange;">**parent constructor**</mark> 有呼叫 <mark style="color:purple;">**overridden methods**</mark>，則 <mark style="color:purple;">**overridden methods**</mark> 會被執行，但此時所提及的任何 <mark style="color:purple;">**this**</mark> 物件<mark style="color:yellow;">**屬性**</mark>都還會是用 <mark style="color:yellow;">**parent class fields**</mark>，因為在這個時間點，<mark style="color:green;">**override class fields**</mark> 還沒有機會初始化❗
{% endhint %}

💾 程式：[replit](https://replit.com/@pegasusroe/JS-derived-class-init-details)

```javascript
const { log } = console;

class A {
    
    // 🔘 F1: class field
    name = 'A'
    
    // ⭐ C1: base constructor
    // ----------------------------------------
    // when "parent constructor" is called:
    //   1. "overridden methods" are used ❗
    //   2. "parent class fields" are used ❗❗
    // ----------------------------------------
    constructor() {
        this.showName();    // ⭐ 1. "overridden method" is used ❗
    }
    
    // 🔸 M1: method
    showName() { 
        // ⭐ 2. "parent class fields" are used ❗❗
        log(`A: name = ${this.name}`); 
    }
}

class B extends A {
    // 🔘 F2: override class field
    name = "B"
    // ⭐ C2: override constructor
    constructor() { 
        super();
        this.showName();    // ⭐ "overridden method" is used❗❗❗
    }
    // 🔸 M2: override method
    showName() { log(`B: name = ${this.name}`); }
}

class C extends B {
    // 🔘 F3: override class field
    name = "C"
    // ⭐ C3: override constructor
    constructor() { 
        super();
        this.showName(); 
    }
    // 🔸 M3: override method
    showName() { log(`C: name = ${this.name}`); }
}

new A();    // "A: name = A"
new B();    // "B: name = A", "B: name = B"
new C();    // "C: name = A", "C: name = B", "C: name = C"

// -----------------------------------------
// process     this            console
// -----------------------------------------
// 🔘 F1:    name = 'A'                      ╮
// ⭐ C1:                                    ├ new A()
// 🔸 M1:                    "A: name = A"   ╯
// -----------------------------------------
// 🔘 F1:    name = 'A'                      ╮
// ⭐ C1:                                    ┊ 
// ❗ M2:                    "B: name = A"   ┊
// 🔘 F2:    name = 'B'                      ├ new B()
// ⭐ C2:                                    ┊
// 🔸 M2:                    "B: name = B"   ╯
// -----------------------------------------
// 🔘 F1:    name = 'A'                      ╮
// ⭐ C1:                                    ┊ 
// ❗ M3:                    "C: name = A"   ┊
// 🔘 F2:    name = 'B'                      ┊
// ⭐ C2:                                    ├ new C()
// ❗ M3:                    "C: name = B"   ┊
// 🔘 F3:    name = 'C'                      ┊
// ⭐ C3:                                    ┊
// 🔸 M3:                    "C: name = C"   ╯
// -----------------------------------------
```
{% endtab %}

{% tab title="⭐️ 重點" %}
⭐️ <mark style="color:red;">**derived class**</mark> initialization：

{% hint style="success" %}
1. 先執行 <mark style="color:purple;">**super()**</mark>。若 <mark style="color:orange;">**parent class**</mark> 為：
   * <mark style="color:yellow;">**base**</mark>**&#x20;class**：
     1. 新增 <mark style="color:purple;">**this**</mark> 物件，並初始化 <mark style="color:yellow;">**base class fields**</mark>。
     2. 執行 <mark style="color:red;">**base constructor**</mark>。
   * <mark style="color:red;">**derived**</mark>**&#x20;class**：\
     (recursive) 過程 1. 2. 3. 再跑一遍。
2. 初始化 <mark style="color:green;">**derived class fields**</mark>。
3. 執行 <mark style="color:red;">**derived constructor**</mark> 裡面 <mark style="color:blue;">**super()**</mark> <mark style="color:red;">**以下**</mark>的初始化動作。
{% endhint %}

{% hint style="info" %}
粗略說就是：

* 先對 <mark style="color:red;">**parent class**</mark> 做初始化 <mark style="color:yellow;">**class fields**</mark>、執行 <mark style="color:purple;">**constructor**</mark>，
* 然後才對<mark style="color:green;">**自己**</mark>做初始化 <mark style="color:yellow;">**class fields**</mark>、執行 <mark style="color:purple;">**constructor**</mark>。
{% endhint %}
{% endtab %}

{% tab title="📗 參考" %}
* [x] JS.info ⟩ [override class fields: a tricky note](https://javascript.info/class-inheritance#overriding-class-fields-a-tricky-note) ⭐️
{% endtab %}
{% endtabs %}
