在 JavaScript 中,ES6 引入了類別(Class)的概念,使得在 JavaScript 中定義和使用類別更加方便。類別定義了對象的特徵(屬性)和行為(方法)。
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
let animal = new Animal('Cat');
animal.speak(); // Cat makes a noise.
建構子(Constructor)是一個特殊的方法,在創建類的新實例時自動調用。它用於初始化新對象的狀態。
在 JavaScript 中,類的建構子方法名稱固定為 constructor
。當使用 new
關鍵字創建類的新實例時,constructor
方法將被自動調用。
以下是一個簡單的 JavaScript 類,演示了如何定義和使用建構子:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
introduce() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
}
}
let person1 = new Person('Alice', 30);
let person2 = new Person('Bob', 25);
person1.introduce(); // Hello, my name is Alice and I'm 30 years old.
person2.introduce(); // Hello, my name is Bob and I'm 25 years old.
在這個例子中,Person
類有一個帶有兩個參數的建構子,用於初始化 name
和 age
屬性。當創建 Person
的新實例時,constructor
方法會自動被調用,並設置對應的屬性值。
值得注意的是,在 JavaScript 中,如果一個類沒有定義自己的建構子,則會隱式地繼承父類的建構子。如果一個類需要進行初始化操作,則應該定義自己的建構子,否則將使用默認的建構子。
公開成員可以被外部代碼訪問和使用。在 JavaScript 中,所有的成員默認都是公開的,因為 JavaScript 的對象是動態的,可以隨時更改和擴展。
class MyClass {
constructor() {
this.publicField = "public";
}
publicMethod() {
console.log("This is a public method.");
}
}
let obj = new MyClass();
console.log(obj.publicField); // public
obj.publicMethod(); // This is a public method.
私有成員只能在類的內部訪問,外部代碼無法直接訪問。在 JavaScript 中,可以使用閉包(Closure)來實現私有成員。
class MyClass {
constructor() {
let privateField = "private";
this.getPrivateField = function() {
return privateField;
};
}
}
let obj = new MyClass();
console.log(obj.privateField); // undefined,私有成員無法直接訪問
console.log(obj.getPrivateField()); // private
受保護成員只能在類的內部和子類中訪問,外部代碼無法直接訪問。在 JavaScript 中,可以使用命名慣例來表示受保護成員,但實際上沒有強制性的機制來限制對它們的訪問。
class MyBaseClass {
constructor() {
this._protectedField = "protected";
}
}
class MySubClass extends MyBaseClass {
getProtectedField() {
return this._protectedField;
}
}
let obj = new MySubClass();
console.log(obj._protectedField); // undefined,受保護成員無法直接訪問
console.log(obj.getProtectedField()); // protected
儘管 JavaScript 沒有原生支持訪問修飾符,但通過上述技巧和慣例,開發者仍然能夠模擬類似的行為。
JavaScript 支援原型繼承,通過 extends
關鍵字實現繼承。
class Dog extends Animal {
speak() {
console.log(this.name + ' barks.');
}
}
let dog = new Dog('Buddy');
dog.speak(); // Buddy barks.
多型是指相同的方法名稱在不同的類別中有不同的實現。在 JavaScript 中,函數重載和方法重載並不是語言的一部分,但可以通過函數的動態特性實現多態。
class Animal {
speak() {
console.log('Animal makes a noise.');
}
}
class Dog extends Animal {
speak() {
console.log('Dog barks.');
}
}
class Cat extends Animal {
speak() {
console.log('Cat meows.');
}
}
let animals = [new Dog(), new Cat()];
animals.forEach(animal => {
animal.speak();
});
封裝是指將數據和方法綁定在一起形成一個單一的單元,並防止外部直接訪問對象的內部狀態。
在 JavaScript 中,封裝可以通過閉包(Closure)、模組化和特定的設計模式(如模組模式和單例模式)來實現。
JavaScript 不直接支援介面(Interface)的概念,但可以通過對象結構、註釋和文檔來模擬介面。
class Shape {
constructor() {
if (this.constructor === Shape) {
throw new Error("Abstract classes can't be instantiated.");
}
}
draw() {
throw new Error("Method 'draw()' must be implemented.");
}
}
class Circle extends Shape {
draw() {
console.log('Drawing Circle');
}
}
let circle = new Circle();
circle.draw(); // Drawing Circle
JavaScript 不直接支援抽象類別的概念,但可以通過將方法實作為空方法或拋出異常來模擬抽象類別。
JavaScript 不直接支援靜態類別的概念,但可以通過將靜態方法添加到類別上來模擬靜態類別。
class MathUtil {
static add(x, y) {
return x + y;
}
static subtract(x, y) {
return x - y;
}
}
console.log(MathUtil.add(5, 3)); // 8
console.log(MathUtil.subtract(5, 3)); // 2
JavaScript 不直接支援列舉的概念,但可以通過使用常量對象、符號和枚舉模式來模擬列舉。
const Colors = {
RED: 'RED',
GREEN: 'GREEN',
BLUE: 'BLUE'
};
console.log(Colors.RED); // RED
JavaScript 不提供類似 C# 或 Java 中的委派(Delegates)概念。但可以通過函數指針、回呼函數和箭頭函數來實現類似的功能。
Lambda 表達式在 JavaScript 中通常指箭頭函數,它提供了一種簡潔的語法來定義匿名函數。
let add = (a, b) => a + b;
console.log(add(3, 4)); // 7
JavaScript 不提供類似 C# 或 Java 中的泛型(Generics)概念。但可以通過對函數的參數或返回值進行類型檢查和轉換,以達到類似泛型的效果。
JavaScript 不提供內置的反射(Reflection)機制,但可以通過一些內置函數和庫來實現對對象結構和屬性的檢查和操作。