ES6中的類和繼承


  • class的寫法及繼承
JavaScript 語言中,生成實例對象的傳統方法是通過構造函數。下面是一個例子
 
 
function Point(x, y) {
  this.x = x;
  this.y = y;}

Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';};

var p = new Point(1, 2);
 
 

上面這種寫法跟傳統的面向對象語言(比如 C++ 和 Java)差異很大,很容易讓新學習這門語言的程序員感到困惑。

ES6 提供了更接近傳統語言的寫法,引入了 Class(類)這個概念,作為對象的模板。通過class關鍵字,可以定義類。

 
基本上,ES6 的 class可以看作只是一個語法糖,它的絕大部分功能,ES5 都可以做到,新的 class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已。上面的代碼用 ES6 的 class改寫,就是下面這樣。
 
//定義類
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }}
上面代碼定義了一個“類”,可以看到里面有一個 constructor方法,這就是構造方法,而 this關鍵字則代表實例對象。也就是說,ES5 的構造函數 Point,對應 ES6 的 Point類的構造方法
 
oint類除了構造方法,還定義了一個 toString方法。注意,定義“類”的方法的時候,前面不需要加上 function這個關鍵字,直接把函數定義放進去了就可以了。另外,方法之間不需要逗號分隔,加了會報錯。
 
ES6 的類,完全可以看作構造函數的另一種寫法
 
class Point {
// ...
}

typeof Point // "function"
上面代碼表明,類的數據類型就是函數,類本身就指向構造函數
 
 
類的屬性名,可以采用表達式。
 
let methodName = 'getArea';

class Square {
  constructor(length) {
  // ...
  }

  [methodName]() {
  // ...
  }}
上面代碼中, Square類的方法名 getArea,是從表達式得到的。
 
 
類內部,默認就是嚴格模式,所以不需要使用 use strict指定運行模式。只要你的代碼寫在類或模塊之中,就只有嚴格模式可用。
 
考慮到未來所有的代碼,其實都是運行在模塊之中,所以 ES6 實際上把整個語言升級到了嚴格模式。
 
 
constructor 方法
 
constructor方法是類的默認方法,通過new命令生成對象實例時,自動調用該方法。一個類必須有constructor方法,如果沒有顯式定義,一個空的constructor方法會被默認添加。
 
class Point {}
// 等同於
class Point {
  constructor() {}}
上面代碼中,定義了一個空的類 Point,JavaScript 引擎會自動為它添加一個空的 constructor方法。
 
constructor方法默認返回實例對象(即 this
 
 
類必須使用 new調用,否則會報錯。這是它跟普通構造函數的一個主要區別,后者不用 new也可以執行。
 
class Foo {
  constructor() {
    return Object.create(null);
  }}

Foo()
// TypeError: Class constructor Foo cannot be invoked without 'new'
 
生成類的實例對象的寫法,與 ES5 完全一樣,也是使用 new命令。前面說過,如果忘記加上 new,像函數那樣調用 Class,將會報錯。
 
class Point {
// ...
}
// 報錯
var point = Point(2, 3);
// 正確
var point = new Point(2, 3);
 
 
類不存在變量提升(hoist),這一點與 ES5 完全不同。
 
new Foo(); // ReferenceError
class Foo {}
 

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

class ColorPoint extends Point {}
 
上面代碼定義了一個 ColorPoint類,該類通過 extends關鍵字,繼承了 Point類的所有屬性和方法。但是由於沒有部署任何代碼,所以這兩個類完全一樣,等於復制了一個 Point類。下面,我們在 ColorPoint內部加上代碼。
 
 
class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y); // 調用父類的constructor(x, y)
    this.color = color;
  }

  toString() {
    return this.color + ' ' + super.toString(); // 調用父類的toString()
  }}
 
上面代碼中, constructor方法和 toString方法之中,都出現了 super關鍵字,它在這里表示父類的構造函數,用來新建父類的 this對象。
 
ES6 要求,子類的構造函數必須執行一次 super函數
 
 
子類必須在constructor方法中調用super方法,否則新建實例時會報錯。這是因為子類自己的this對象,必須先通過父類的構造函數完成塑造,得到與父類同樣的實例屬性和方法,然后再對其進行加工,加上子類自己的實例屬性和方法。如果不調用super方法,子類就得不到this對象。
 
 
class Point { /* ... */ }

class ColorPoint extends Point {
  constructor() {
  }}

let cp = new ColorPoint(); // ReferenceError
 
上面代碼中, ColorPoint繼承了父類 Point,但是它的構造函數沒有調用 super方法,導致新建實例時報錯。
 
 
需要注意的地方是,在子類的構造函數中,只有調用super之后,才可以使用this關鍵字,否則會報錯。這是因為子類實例的構建,是基於對父類實例加工,只有super方法才能返回父類實例
 
 
 
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }}

class ColorPoint extends Point {
  constructor(x, y, color) {
    this.color = color; // ReferenceError
    super(x, y);
    this.color = color; // 正確
  }}
上面代碼中,子類的 constructor方法沒有調用 super之前,就使用 this關鍵字,結果報錯,而放在 super方法之后就是正確的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM