tc39 proposal: Classes private methods and getter/setters

zhangbao發表於2020-10-01

提案地址:github.com/tc39/proposal-private-methods

該提案是對 class field declarations 提案中關於私有成員語法的補充,進一步為 class 引入了 private methods and accessors (getter/setters)。目前處於 Stage 3 階段。

與宣告私有私有成員一樣的是,私有方法和私有訪問器都使用 # 作為字首標識。

為了更好地說明該提案中它引入功能的使用場景。先以一個功能為例:

// 自定義元素:點選後,實現數值自增
class Counter extends HTMLElement {
    #xValue = 0;

    constructor() {
        super();
        this.onclick = this.clicked.bind(this);
    }

    get x() {
        return this.#xValue;
    }

    set x(value) {
        this.#xValue = value;
        window.requestAnimationFrame(this.render.bind(this));
    }

    clicked() {
        this.x++;
    }

    connectedCallback() {
        this.render();
    }

    render() {
        this.textContent = this.x.toString();
    }
}

// 以 <num-counter> 標籤的形式註冊
window.customElements.define('num-counter', Counter);

這裡 xValue 被封裝成了私有成員,只供在內部訪問。按照提案中的解釋,這種方式帶來的好處是:

By declaring fields up-front, class definitions become more self-documenting; instances go through fewer state transitions, as declared fields are always present.

大致是說,提前宣告變數的方式,更直接自然。狀態初始化已在開頭完成,類中的邏輯程式碼會更加緊湊。

但這樣的程式碼還有最佳化的空間,我們希望這個自定義的元素的表現更接近於原生元件。

比如,這裡的訪問器屬性 xclickedrender 方法,應該只是元素內部的狀態,而不應該對外暴露給外面。因此,我們可以做出如下修改,以達到目的。

class Counter extends HTMLElement {
    #xValue = 0;

    constructor() {
        super();
        this.onclick = this.#clicked.bind(this);
    }

    get #x() {
        return this.#xValue;
    }

    set #x(value) {
        this.#xValue = value;
        window.requestAnimationFrame(this.#render.bind(this));
    }

    #clicked() {
        this.#x++;
    }

    connectedCallback() {
        this.#render();
    }

    #render() {
        this.textContent = this.#x.toString();
    }
}

window.customElements.define('num-counter', Counter);

With all of its implementation kept internal to the class, this custom element can present an interface which is basically just like a built-in HTML element. Users of the custom element don’t have the power to mess around with any of its internals.

這樣一來,使用者怎麼著也不會誤操作 Counter 例項的內部方法了。

Tip:
需要額外注意的是,本提案引入的 private methods and accessors (getter/setters) 功能,僅是針對 class 的,不針對物件字面量。在物件字面量中使用會報錯。

(完)

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章