# init static property

[JS](https://lochiwei.gitbook.io/web/js) ⟩ [value](https://lochiwei.gitbook.io/web/js/val) ⟩ [object](https://lochiwei.gitbook.io/web/js/val/obj) ⟩ [class](https://lochiwei.gitbook.io/web/js/val/class) ⟩ [member](https://lochiwei.gitbook.io/web/js/val/class/member) ⟩ [static](https://lochiwei.gitbook.io/web/js/val/class/member/static) ⟩ init&#x20;

{% hint style="info" %}
本篇討論： [#how-to](#how-to "mention")
{% endhint %}

{% tabs %}
{% tab title="👥 相關" %}

* [init](https://lochiwei.gitbook.io/web/js/val/class/init/init "mention")：用於對 [static property](https://lochiwei.gitbook.io/web/js/val/class/member/static) 的初始化
* [component](https://lochiwei.gitbook.io/web/component "mention")：可用這裡的方法初始化 component 的靜態屬性
  {% endtab %}

{% tab title="💾 程式" %}
⭐️ static members

{% hint style="warning" %}
:star: 注意：<mark style="color:yellow;">static getter</mark> <mark style="color:blue;">`static get c() {}`</mark> <mark style="color:red;">不能省略</mark> <mark style="color:blue;">`get`</mark>，不然會變成 <mark style="color:yellow;">static method</mark> <mark style="color:blue;">`static c() {}`</mark>:exclamation:
{% endhint %}

```javascript
class A {
  static a;                 // A.a = undefined
  static b = 0;             // A.b   (static property: initialized)
  static get c() { ... }    // A.c   (static getter)
  static d() { ... }        // A.d() (static method)
}
```

⭐️ private static members

{% hint style="warning" %}

* accessable <mark style="color:yellow;">only within the class body</mark>.
* private members are <mark style="color:yellow;">not inherited</mark>.
  {% endhint %}

```javascript
class A {
  // ⭐️ "#" means "private"
  static #e;                // A.#e    (private static property: uninitialized)
  static get #f() { ... }   // A.#f    (private static getter)
  static #g() { ... }       // A.#g()  (private static method)
}
```

{% endtab %}

{% tab title="📘 手冊" %}

* MDN ⟩ [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript) ⟩ [Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference) ⟩ [Classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) ⟩&#x20;
  * [static](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static)
  * [Static initialization blocks](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Static_initialization_blocks)
    {% endtab %}

{% tab title="📗 參考" %}

* [ ] [JS.info ⟩ class ⟩ Static properties and methods](https://javascript.info/static-properties-methods)
* [ ] ChatGPT ⟩ [static property init](https://chatgpt.com/share/676ccd2d-bc5c-800e-bb4a-9ec7c4fb546f)&#x20;
  {% endtab %}
  {% endtabs %}

## 如何初始化靜態屬性 <a href="#how-to" id="how-to"></a>

{% tabs %}
{% tab title="⚖️ 比較" %}

<table><thead><tr><th width="79" align="center">方法</th><th width="84" align="center">推薦</th><th>優點</th><th>缺點</th></tr></thead><tbody><tr><td align="center">1</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="1f44d">👍</span></td><td>✅ 延遲初始化</td><td><span data-gb-custom-inline data-tag="emoji" data-code="26a0">⚠️</span> 額外的私有靜態屬性</td></tr><tr><td align="center">2</td><td align="center"></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="26a0">⚠️</span> 不夠模組化</td></tr><tr><td align="center">3</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="1f44d">👍</span></td><td>✅ 模組化</td><td><span data-gb-custom-inline data-tag="emoji" data-code="26a0">⚠️</span> <mark style="color:orange;">ES2022</mark></td></tr><tr><td align="center">4</td><td align="center"></td><td>✅ 模組化</td><td></td></tr></tbody></table>
{% endtab %}

{% tab title="1" %}
方法一：使用 [static](https://lochiwei.gitbook.io/web/js/val/class/member/static) [getter](https://lochiwei.gitbook.io/web/js/val/class/member/getter-setter)

```javascript
class ClassA {
	
	// ClassA.CONSTANT
	// 方法一：使用 static getter（傳回 ClassA._CONSTANT 的值）
	// • 優點：
	//   ✅ 延遲初始化 
	// • 缺點：
	//   ❗ 額外的私有靜態屬性 (ClassA._CONSTANT)
	// ⭐️ 注意：不能省略 `get`，不然會變成 static method❗
	static get CONSTANT() {
		
		// 如果還沒初始化
		// ⭐️ in static method/block/getter, this == class itself.
		if (!this._CONSTANT) {
			// 執行初始化 ...，然後將結果存在私有靜態屬性中
			this._CONSTANT = 100; 
		}
		
		return this._CONSTANT;
	}
	
}
```

{% endtab %}

{% tab title="2" %}
方法二：在 class 定義後立即計算賦值

```javascript
class ClassB {
  	// ClassB.CONSTANT
	// 方法二：在 class 定義後立即計算賦值
	// • 缺點：
	//   ❗程式碼不夠模組化
	static CONSTANT;	// 1. 先宣告
}

// block
{
	// 複雜的初始化邏輯 ...
	ClassB.CONSTANT = 200;	// 2. 後面立即計算賦值
}
```

{% endtab %}

{% tab title="3" %}
方法三：使用 [static block](https://lochiwei.gitbook.io/web/js/val/class/init/init) (<mark style="color:orange;">ES2022</mark>)（<mark style="color:yellow;">方法二的現代版</mark>）

```javascript
class ClassC {
	
	// ClassC.CONSTANT  
	// 方法三：使用 static block (ES2022)（方法二的現代版）
	// • 優點：
	//   ✅ 模組化（沒有程式碼外漏於 class 定義外）
	//   ✅ 語法簡潔，不需外部的計算(方法二)、或內部的靜態方法(方法四)
	static CONSTANT;			// 1. 先宣告
	  
	// ⭐️ static block (ES2022)
	// ⭐️ in static method/block/getter, this == class itself.
	static {						
		// 複雜的初始化邏輯 ...
		this.CONSTANT = 300;		// 2. 後面立即計算賦值
	}
}
```

{% endtab %}

{% tab title="4" %}
方法四：使用 [static method](https://lochiwei.gitbook.io/web/js/val/builtin/arr/static-methods) 賦值

```javascript
class ClassD {
  
	// ClassD.CONSTANT
	// 方法四：使用 static method 賦值
	// • ✅ 優點：模組化（沒有程式碼外漏於 class 定義外）
	// ⭐️ in static method/block/getter/declaration, this == class itself.
	static CONSTANT = this.initStaticConstant();

	static initStaticConstant() {
    	// 複雜的初始化邏輯 ...
		return 400;
	}
}
```

{% endtab %}

{% tab title="💈範例" %}

* codepen ⟩ [static property init](https://codepen.io/pegasusroe/pen/JoPJQXp)&#x20;
  {% endtab %}
  {% endtabs %}
