附录A: ES6 class
最后更新于:2022-04-02 02:03:42
# 附录A: ES6 `class`
如果说本书后半部分(第四到六章)有什么关键信息,那就是类是一种代码的可选设计模式(不是必要的),而且用像 JavaScript 这样的 `[[Prototype]]` 语言来实现它总是很尴尬。
虽然这种尴尬很大一部分关于语法,但 *不仅* 限于此。第四和第五章审视了相当多的难看语法,从使代码杂乱的 `.prototype` 引用的繁冗,到 *显式假想多态*:当你在链条的不同层级上给方法相同的命名以试图实现从低层方法到高层方法的多态引用。`.constructor` 被错误地解释为“被XX构建”,这成为了一个不可靠的定义,也成为了另一个难看的语法。
但关于类的设计的问题要深刻多了。第四章指出在传统的面向类语言中,类实际上发生了从父类向子类,由子类向实例的 *拷贝*动作,而在 `[[Prototype]]` 中,动作 不是 一个拷贝,而是相反 —— 一个委托链接。
OLOO 风格和行为委托接受了 `[[Prototype]]`,而不是将它隐藏起来,当比较它们的简单性时,类在 JS 中的问题就凸显出来。
## `class`
我们 *不必* 再次争论这些问题。我在这里简单地重提这些问题仅仅是为了使它们在你的头脑里保持新鲜,以使我们将注意力转向 ES6 的 `class` 机制。我们将在这里展示它如何工作,并且看看 `class` 是否实质上解决了任何这些“类”的问题。
让我们重温第六章的 `Widget`/`Button` 例子:
```source-js
class Widget {
constructor(width,height) {
this.width = width || 50;
this.height = height || 50;
this.$elem = null;
}
render($where){
if (this.$elem) {
this.$elem.css( {
width: this.width + "px",
height: this.height + "px"
} ).appendTo( $where );
}
}
}
class Button extends Widget {
constructor(width,height,label) {
super( width, height );
this.label = label || "Default";
this.$elem = $( "
';