tc39 proposal: Classes private methods and getter/setters

提案地址: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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!