Classes

翻譯不完整。請協助 翻譯此英文文件

ECMAScript 6 中引入了類別 (classes) 作為 JavaScript 現有 prototype-based 繼承的語法糖,class 語法並不是要引入新的物件導向繼承模型到 JavaScript 中,JavaScript 類別提供了一個更簡潔的語法來建立物件和處理繼承。

定義類別

類別實際上是函數(functions),就跟你可以定義函數敘述和函數宣告一樣,類別的語法有兩個元件:類別敘述(class expressions)和類別宣告(class declarations)。

類別宣告

一個定義類別的方法是使用類別宣告(class declaration),要宣告一個類別,你要使用關鍵字 class 搭配類別名稱(此例為 "Polygon")。

class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

Hoisting

函數宣告和類別宣告的一個重要差別在於函數宣告是 hoisted ,類別宣告則不是, 你需要先宣告你的類別,然後存取他,否則像是下面的程式碼就會丟出一個 ReferenceError:

var p = new Polygon(); // ReferenceError

class Polygon {}

類別敘述

類別敘述是定義類別的另一種方法,類別敘述可以有名稱或是無名稱,賦予一個有名稱類別敘述的名稱只在類別主體(class's body)中有作用。

// unnamed
var Polygon = class {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};

// named
var Polygon = class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};

類別主體與方法定義

類別的主體指的是被大括號({})包含的部分,你可以在這裡定義類別成員(members),例如方法(methods)或建構子(constructors)。

Strict mode

類別宣告 與 類別敘述 的主體會以 strict mode 執行。

建構子

建構子(constructor)方法是一個特別的方法,用來建立和初始化一個類別的物件,一個類別只能有一個名為 "constructor" 的特別方法,當類別中含有一個以上的 construtor 方法時,SyntaxError 將會被拋出。

一個建構子可以用關鍵字 super 來呼叫父類別的建構子。

原型方法(Prototype methods)

參見 method definitions

class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
  
  get area() {
    return this.calcArea()
  }

  calcArea() {
    return this.height * this.width;
  }
}

靜態方法(Static methods)

關鍵字 static 定義了一個類別的靜態方法,靜態方法不需要實體化它所屬類別的實例就可以被呼叫,它也無法被已實體化的類別物件呼叫,靜態方法經常被用來建立給應用程式使用的工具函數。

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    static distance(a, b) {
        const dx = a.x - b.x;
        const dy = a.y - b.y;

        return Math.sqrt(dx*dx + dy*dy);
    }
}

const p1 = new Point(5, 5);
const p2 = new Point(10, 10);

console.log(Point.distance(p1, p2));

extends 建立子類別

關鍵字 extends 是用來在類別宣告或是類別敘述中建立子類別的方法。

class Animal { 
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

class Dog extends Animal {
  speak() {
    console.log(this.name + ' barks.');
  }
}

子類別類建物建

TBD

裝箱(boxing) 遇到 prototype 和static 方法

當 static 或 prototype 方法在一個非物件實體的 "this"下被呼叫,或者說 "this" 的值是 Boolean, string, number, undefined, null 等情況時,在函數內部 this 的值將會是 undefined。自動裝箱 (autoboxing)在這裡並不會發生。這樣的行為就算我們是在非 strict 模式下寫作也是一樣。

class Animal { 
  speak() {
    return this;
  }
  static eat() {
    return this;
  }
}

let obj = new Animal();
let speak = obj.speak;
speak(); // undefined

let eat = Animal.eat;
eat(); // undefined

而如果我們採用傳統的以函數為類別基礎的寫法,那麼將會以函數呼叫時的 'this' 的內容進行自動裝箱 (autoboxing)。

function Animal() { }

Animal.prototype.speak = function(){
  return this;
}

Animal.eat = function() {
  return this;
}

let obj = new Animal();
let speak = obj.speak;
speak(); // global object

let eat = Animal.eat;
eat(); // global object

super 呼叫父類別

關鍵字 super 用來提供一個類別呼叫其父類別的函數

class Cat { 
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

class Lion extends Cat {
  speak() {
    super.speak();
    console.log(this.name + ' roars.');
  }
}

ES5 繼承語法與 ES6 類別語法的比較

TBD

範例

TBD

規格

規格 狀態 評論
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Class definitions' in that specification.
Standard Initial definition.

瀏覽器相容性

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support 42.0 Nightly build ? No support 9.0
Feature Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile Chrome for Android
Basic support No support Nightly build ? ? ? 42.0

 

See also

文件標籤與貢獻者

 此頁面的貢獻者: ywchiao, fbukevin
 最近更新: ywchiao,