simple's Studio.

ES6中的super和extends

2017/11/03

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); 
  }
}
CATALOG