# member

[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

{% hint style="success" %}

{% endhint %}

{% tabs %}
{% tab title="🔴 主題" %}

* object [prop](https://lochiwei.gitbook.io/web/js/val/obj/prop "mention")
* [field](https://lochiwei.gitbook.io/web/js/val/class/member/field "mention")
* [getter-setter](https://lochiwei.gitbook.io/web/js/val/class/member/getter-setter "mention")
* [computed](https://lochiwei.gitbook.io/web/js/val/obj/prop/name/computed "mention")
  {% endtab %}

{% tab title="💾 程式" %}

* [replit](https://replit.com/@pegasusroe/JS-class-definition#index.js)

```javascript
const { log } = console;

// ⭐️ class definition
// --------------------------------------------------------
// ❌ GAS doesn't support (static/instance) "class fields".
// ✅ GAS does support "static methods/getters/setters".

class User {

    // -------------------------
    //     ⭐️ static members
    // -------------------------
    
    // ❌ GAS 不支援 (static) "class fields".
    // ✅ 可用 static getters/setters 代替.
    static planet = "Earth";           // static property

    // ✅ GAS 支援 "(static) methods/getters/setters".
    static staticMethod() {            // static method
        return 'static method'
    }

    // -----------------------------------------------------
    //     ⭐️ static getters/setters as static properties
    // -----------------------------------------------------
    
    // ✅ GAS 可用這個來代替 static class fields.
    static get age() { return this._age }    // getter

    static set age(value) {                   // setter
        if (value < 0) { log(`age cannot be negative: ${value}`); return; }
        this._age = value
    }

    // -------------------------
    //     ⭐️ class fields
    // -------------------------
    
    // ❌ GAS 不支援 "class fields".
    // ✅ 可用 getters/setters 代替.
    age = 0;                                // regular class field
    hobby = prompt('any hobby?', "game");   // ⭐️ function value as property value
    boundMethod = () => { };                // 🔗 bound method (`this` === instance)

    // -------------------------
    //     ⭐️ getters/setters
    // -------------------------
    
    // ✅ GAS 可用這個來代替 instace class fields.
    get name() { return this._name }    // getter

    set name(value) {                   // setter
        this._name = value
    }

    // -----------------
    //     ⭐️ methods
    // -----------------

    constructor() { }                    // ⭐️ constructor
    method() { }                         // regular method
    ['say' + 'Hi']() { log(`hello`) }     // ⭐ computed-name method
}

// test code
let user = new User('Mary');
user.name = 'Joe';                      // ⭐ setter: this._name = 'Joe'
user.sayHi();                           // "hello"

// test static getter/setter
User.age = -9;                          // "age cannot be negative: -9"
User.age = 10;

[
    user.name,           // "Joe"
    user.hobby,
    user.planet,         // undefined

    User.planet,         // "Earth"
    User.staticMethod(), // "static method"

    User.age,            // 10

].forEach(x => log(x));

// ⭐️ class expression
// ---------------------------------------------------------------
let User2 = class {
  sayHi() {}
};

// ⭐️ class expression as return value
// ---------------------------------------------------------------
function returnUserClass(){
    return class {
      sayHi() {}
    };
}
```

{% endtab %}

{% tab title="⭐️ 重點" %}
class 定義背後有幾個分解動作：

{% hint style="info" %}

* class 本身是個 Function (有 prototype)
* static members 放到 class 本身
* instance methods (含 constructor)，放到 prototype。
* constructor() 內的 this.prop 屬性放到 instance。
* 為 class 跟它的 prototype 設定 prototype chain (\_\_proto\_\_ 屬性)，如下表：<br>
  {% endhint %}

```
object              prototype chain (.__proto__)
-----------------------------------------
Animal              Function.prototype
Rabbit              Animal.prototype
Animal.prototype    Object.prototype
Rabbit.prototype    Animal.prototype
```

也就是說，透過 class 語法宣告的 Animal，其實是宣告了一個 **function** Animal，與一個 Animal.**prototype** (在 class body 內定義的方法都放在這裡)。

![](https://2527454625-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MfvEFZnSBhKT6fJmus0%2Fuploads%2Fw2vijJLr06wVDDdFaBJM%2Fclass%20def%202.jpg?alt=media\&token=ba882f72-dc43-422a-af7f-cdf2ee0a3561)
{% endtab %}

{% tab title="📜 結構圖" %}
![](https://2527454625-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MfvEFZnSBhKT6fJmus0%2Fuploads%2FLClnXPpOBGfkGsxnyRju%2Fclass%20def%201.jpg?alt=media\&token=f1580c39-dc2c-4bf2-8685-09634c1989fd)
{% endtab %}

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

* JS.info ⟩ [Classes](https://javascript.info/classes)
  {% endtab %}

{% tab title="🗣 討論" %}

* [How to use static method in google app script](https://stackoverflow.com/questions/69202290/how-to-use-static-method-in-google-app-script)
  {% endtab %}
  {% endtabs %}
