tc39 proposal: Classes private methods and getter/setters
该提案是对 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.
大致是说,提前声明变量的方式,更直接自然。状态初始化已在开头完成,类中的逻辑代码会更加紧凑。
但这样的代码还有优化的空间,我们希望这个自定义的元素的表现更接近于原生组件。
比如,这里的访问器属性 x
,clicked
和 render
方法,应该只是元素内部的状态,而不应该对外暴露给外面。因此,我们可以做出如下修改,以达到目的。
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 协议》,转载必须注明作者和本文链接