ES6 在 JavaScript 中引入「類別」的概念,與其他程式設計語言的類別不同。這裡的類別是特殊函式,可做為範本使用,用來建立已含有資料的物件、與該資料相關聯的屬性,以及與這些資料操控相關的方法。這些物件、屬性和方法統稱為類別的「成員」。
若要定義類別,請使用 class
關鍵字。按照 JavaScript 內建建構函式函式製定的最佳做法和慣例,為類別的任何 ID 以大寫字母開頭:
class MyClass {}
類別旨在提供更易於存取的方式,以便處理原型和建構函式函式的進階功能:
class MyClass {}
typeof MyClass;
> "function"
由於類別已部分新增,使使用進階 JavaScript 功能更容易使用,也更吸引人,因此有時也稱為「語法糖」。不過,類別除了能針對原型繼承作業提供實用的簡短資訊,隆重推出類別語法創造機會,解決 JavaScript 長期以來的設計問題,而且不會導入回溯相容性問題。舉例來說,類別主體中的所有程式碼一律會以嚴格模式評估。
如要建立類別的執行個體,請使用 new
運算子。
class MyClass {}
const myClassInstance = new MyClass();
myClassInstance;
> Object { }
類別主體中定義的函式會以該類別每個例項的方法公開。
class MyClass {
classMethod() {
console.log( "My class method." );
}
}
const myClassInstance = new MyClass();
myClassInstance.classMethod();
> "My class method."
類別中定義的方法會成為結果例項原型上的方法。由於原型鏈具有性質,您可以直接對產生的物件呼叫這些方法:
class MyClass {
classMethod() {
console.log( "My class method." );
}
}
const myClassInstance = new MyClass( "A string." );
myClassInstance;
> Object { }
<prototype>: Object { … }
classMethod: function classMethod()
constructor: class MyClass { constructor(myPassedValue) }
<prototype>: Object { … }
myClassInstance.classMethod();
> "My class method."
建立類別的執行個體會呼叫特殊的 constructor()
方法,對新建立的執行個體執行所有必要的「設定」,並初始化相關聯的所有屬性。建立執行個體時,傳送至該類別的任何引數都可以提供給 constructor()
方法:
class MyClass {
constructor( myPassedValue ) {
console.log( myPassedValue );
}
}
const myClassInstance = new MyClass( "A string." );
> "A string."
在類別主體中,this
的值是指執行個體本身,而 this
中定義的任何屬性都會公開為該類別各例項的屬性:
class MyClass {
constructor( myPassedValue ) {
this.instanceProperty = myPassedValue;
}
}
const myClassInstance = new MyClass( "A string." );
myClassInstance;
> Object { instanceProperty: "A string." }
這些屬性也能提供給類別主體中的所有方法:
class MyClass {
constructor( myPassedValue ) {
this.instanceProp = myPassedValue;
}
myMethod() {
console.log( this.instanceProp );
}
}
const myClassInstance = new MyClass( "A string." );
myClassInstance.myMethod();
> "A string."
如果您未為類別定義 constructor()
,JavaScript 引擎會假設空白的「預設」constructor
。每個類別只能有一個名為 constructor()
的特殊方法:
class MyClass {
constructor() {}
constructor() {}
}
> Uncaught SyntaxError: A class may only have one constructor
您可以使用「類別宣告」或「類別運算式」來定義類別。先前的範例全都是類別宣告,因此必須使用 new
叫用名稱。類別運算式可以或不命名,建立「匿名」類別。
let ClassExpression = class {
constructor() {}
};
ClassExpression;
> class {}
您可以將匿名類別運算式用於「即時」建構類別的函式:
function classMaker() {
return class {
constructor() {}
};
}
let MyVariable = classMaker();
MyVariable;
> class {}
使用類別宣告重新宣告類別會導致語法錯誤:
class MyClass {
constructor( ) {
console.log( "My class." );
}
};
class MyClass {
constructor() {
console.log( "My new class." );
}
};
> Uncaught SyntaxError: redeclaration of class MyClass
不過,類別運算式可讓您重新定義類別:
let ClassExpression = class MyClass { };
ClassExpression = class MyOtherClass {
constructor( myString ) {
this.myProp = myString;
}
};
new ClassExpression( "String." );
> MyOtherClass {myProp: 'String.'}
您無法以類別宣告的方式叫用已命名的類別運算式。不過,系統會將類別運算式的指派名稱當做已建立執行個體的屬性來使用,這主要是簡化偵錯作業:
let MyVariable = class MyClass {};
MyClass;
> Uncaught ReferenceError: MyClass is not defined
MyVariable;
> class MyClass {}
MyVariable.name;
> "MyClass"
使用類別運算式初始化變數時,系統會如預期遵循該變數的提升規則。類別宣告遵循與 let
和 const
相同的「暫時無效區域」規則,且行為會像是未提升至目前範圍的頂部,這表示在類別宣告之前叫用類別會導致錯誤:
{
let myVar = new MyClass( "Property string." );
class MyClass {
myProp;
constructor( myString ) {
this.myProp = myString;
}
};
};
> Uncaught ReferenceError: Cannot access 'MyClass' before initialization
隨堂測驗
以下何者正確定義類別?
class MyClass {}
myClass = class {}
new class()
一個類別可以有多少個 constructor()
方法?