ES6 中的子类
我们已经了解了如何在 JavaScript 中创建类。现在使用新的 super 和 extends 关键字扩展类。
class Tree {
constructor(size = '10', leaves = {spring: 'green', summer: 'green', fall: 'orange', winter: null}) {
this.size = size;
this.leaves = leaves;
this.leafColor = null;
}
changeSeason(season) {
this.leafColor = this.leaves[season];
if (season === 'spring') {
this.size += 1;
}
}
}
class Maple extends Tree {
constructor(syrupQty = 15, size, barkColor, leaves) {
super(size, barkColor, leaves);
this.syrupQty = syrupQty;
}
changeSeason(season) {
super.changeSeason(season);
if (season === 'spring') {
this.syrupQty += 1;
}
}
gatherSyrup() {
this.syrupQty -= 3;
}
}
const myMaple = new Maple(15, 5);
myMaple.changeSeason('fall');
myMaple.gatherSyrup();
myMaple.changeSeason('spring');
Tree 和 Maple 都是 JavaScript 类。Maple 类是 Tree 的子类,并使用关键字 extends 将自己设为子类。要让子类可以访问到父类,需要使用关键字 super。注意到 super 有两种使用方式吗?在 Maple 的构造方法中,super 被用作函数。在 Maple 的changeSeason() 方法中,super 被用作对象!
与 ES5 子类对比
我们看看用 ES5 编写相同功能的代码:
function Tree() {
this.size = size || 10;
this.leaves = leaves || {spring: 'green', summer: 'green', fall: 'orange', winter: null};
this.leafColor;
}
Tree.prototype.changeSeason = function(season) {
this.leafColor = this.leaves[season];
if (season === 'spring') {
this.size += 1;
}
}
function Maple (syrupQty, size, barkColor, leaves) {
Tree.call(this, size, barkColor, leaves);
this.syrupQty = syrupQty || 15;
}
Maple.prototype = Object.create(Tree.prototype);
Maple.prototype.constructor = Maple;
Maple.prototype.changeSeason = function(season) {
Tree.prototype.changeSeason.call(this, season);
if (season === 'spring') {
this.syrupQty += 1;
}
}
Maple.prototype.gatherSyrup = function() {
this.syrupQty -= 3;
}
const myMaple = new Maple(15, 5);
myMaple.changeSeason('fall');
myMaple.gatherSyrup();
myMaple.changeSeason('spring');
这段代码和上面的类风格的代码都实现了相同的功能。
#使用子类
像大多数新增加的特性,使用 class、super 和 extends 创建子类时设置代码少了很多,语法更清晰。
只需记住,在底层,函数和原型之间的连接是一样的。
super 必须在 this 之前被调用
在子类构造函数中,在使用 this 之前,必须先调用超级类。
class Apple {}
class GrannySmith extends Apple {
constructor(tartnessLevel, energy) {
this.tartnessLevel = tartnessLevel; // `this` before `super` will throw an error!
super(energy);
}
}