再理解es6 中的 class super extends

Pandaaa發表於2018-07-06

說明

  • 適用於 es6 初學者
  • 理解 class 的使用

extends 繼承

  • class 可以通過 extends 關鍵字實現繼承,這比 ES5 的通過修改原型鏈實現繼承,要清晰和方便很多。
class Point{
    
}

class ColorPoint extends Point{
    
}
複製程式碼

上面程式碼定義了一個ColorPoint類,該類通過extends關鍵字,繼承了Point類的所有屬性和方法。但是由於沒有部署任何程式碼,所以這兩個類完全一樣,等於複製了一個Point類。下面,我們在ColorPoint內部加上程式碼。

super 呼叫父類 constructor

class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y); // 呼叫父類的constructor(x, y)
    this.color = color;
  }

  toString() {
    return this.color + ' ' + super.toString(); // 呼叫父類的toString()
  }
}
複製程式碼
  • super 來呼叫父類的 constructor

子類沒有定義 constructor,會預設新增

class ColorPoint extends Point {
}

// 等同於
class ColorPoint extends Point {
  constructor(...args) {
    super(...args);
  }
}
複製程式碼

合理的使用 super

super 當做函式呼叫

  • 第一種情況,super 關鍵字作為函式呼叫。es6 中,子類的建構函式必須執行一次 super(記住我們可以不寫 constructor 和 super ,函式會自動新增上,看?的 case
class A {}

class B extends A {
  constructor() {
    super();
  }
}
複製程式碼

注意,super雖然代表了父類A的建構函式,但是返回的是子類B的例項,即super內部的this指的是B,因此super()在這裡相當於A.prototype.constructor.call(this)

class A {
  constructor() {
    console.log(new.target.name);
  }
}
class B extends A {
  constructor() {
    super();
  }
}
new A() // A
new B() // B
複製程式碼

上面程式碼中,new.target指向當前正在執行的函式。可以看到,在super()執行時,它指向的是子類B的建構函式,而不是父類A的建構函式。也就是說,super()內部的this指向的是B。

super 當做物件使用

  • 第二種情況,super作為物件時,在普通方法中,指向父類的原型物件;在靜態方法中,指向父類。
class A {
  p() {
    return 2;
  }
}

class B extends A {
  constructor() {
    super();
    console.log(super.p()); // 2
  }
}

let b = new B();
複製程式碼

相關文章