JS 中 class 與 extends 關鍵詞的使用詳解
在 JavaScript 面向對象編程中,class和extends是 ES6 引入的核心關鍵詞,它們為原本基於原型鏈的繼承體系提供了更簡潔、更符合傳統面向對象語法的封裝。class用於定義類(可以理解為對象的 “模板”),extends則用於實現類的繼承,讓子類能夠複用父類的屬性和方法,同時支持擴展自身功能。這對關鍵詞的出現,讓 JS 的面向對象編程更直觀、更易維護,成為現代前端框架(如 React、Vue)和大型項目開發中的常用語法。
class關鍵詞的核心作用是定義一個類,類中可以包含構造函數、實例方法、靜態方法、 getter/setter 等成員。與傳統的原型鏈寫法相比,class語法更簡潔,結構更清晰,無需手動操作原型對象,就能輕鬆創建可實例化的 “模板”。
class 基礎用法:定義類與實例化
// 定義一個Person類
class Person {
// 構造函數:初始化實例屬性,new時自動執行
constructor(name, age) {
this.name = name; // 實例屬性:每個實例獨有的屬性
this.age = age;
}
// 實例方法:掛載到實例原型上,所有實例共享
sayHello() {
console.log(`大家好,我是${this.name},今年${this.age}歲`);
}
// 靜態方法:用static修飾,掛載到類本身,只能通過類調用
static createAdult(name) {
return new Person(name, 18); // 靜態方法常用於創建實例的工具函數
}
// getter:獲取屬性時觸發,用於封裝屬性計算邏輯
get isAdult() {
return this.age >= 18;
}
// setter:設置屬性時觸發,用於限制屬性賦值邏輯
set age(value) {
if (value > 120) {
throw new Error("年齡必須在0-120之間");
}
this._age = value; // 用下劃線區分實際存儲的屬性
}
get age() {
return this._age;
}
}
// 1. 實例化類:通過new關鍵字創建實例
const person1 = new Person("張三", 25);
person1.sayHello(); // 輸出:大家好,我是張三,今年25歲
console.log(person1.isAdult); // 輸出:true
// 2. 調用靜態方法創建實例
const person2 = Person.createAdult("李四");
person2.sayHello(); // 輸出:大家好,我是李四,今年18歲
// 3. setter的限制作用
const person3 = new Person("王五", 150); // 報錯:年齡必須在0-120之間
需要注意的是,class本質上是原型鏈的語法糖,它並沒有改變 JS 基於原型的繼承本質,但簡化了語法。比如person1.__proto__依然指向Person.prototype,實例方法依然是共享的,但class屏蔽了原型操作的細節,讓代碼更易讀。
extends 關鍵詞:實現類的繼承
extends用於創建一個子類,繼承父類的所有屬性和方法(除了私有成員)。子類可以通過super()調用父類的構造函數和方法,也可以重寫父類的方法,實現功能擴展。這是代碼複用的核心方式,比如在項目中定義 “基礎類” 封裝通用邏輯,再通過子類擴展特定功能。
基礎繼承示例:子類複用父類功能
// 定義子類Student,繼承自Person父類
class Student extends Person {
// 子類構造函數:必須先調用super(),再定義自身屬性
constructor(name, age, studentId, grade) {
super(name, age); // 調用父類構造函數,初始化name和age
this.studentId = studentId; // 子類特有屬性
this.grade = grade;
}
// 重寫父類方法:覆蓋父類的sayHello
sayHello() {
super.sayHello(); // 調用父類的sayHello方法
console.log(`我的學號是${this.studentId},在讀${this.grade}年級`);
}
// 子類特有方法
study(subject) {
console.log(`${this.name}正在學習${subject}`);
}
// 重寫靜態方法
static createHighSchoolStudent(name, studentId) {
return new Student(name, 16, studentId, "高中");
}
}
// 實例化子類
const student1 = new Student("趙六", 17, "S2024001", "高二");
student1.sayHello();
// 輸出:
// 大家好,我是趙六,今年17歲
// 我的學號是S2024001,在讀高二年級
student1.study("JavaScript"); // 輸出:趙六正在學習JavaScript
console.log(student1.isAdult); // 輸出:false(繼承父類的getter)
// 調用子類的靜態方法
const student2 = Student.createHighSchoolStudent("孫七", "S2024002");
student2.sayHello();
// 輸出:
// 大家好,我是孫七,今年16歲
// 我的學號是S2024002,在讀高二年級
繼承中的注意事項
-
子類構造函數中必須先調用****super(),才能使用this關鍵字,否則會報錯。super()的作用是初始化父類的實例屬性,確保子類繼承的屬性正常掛載。
-
子類可以重寫父類的實例方法、靜態方法和 getter/setter,重寫後會優先執行子類的邏輯。
-
父類的私有成員(用#開頭定義)不會被子類繼承,子類無法訪問。
私有成員與繼承限制示例:
class Parent {
#privateProp = "私有屬性"; // 私有成員:用#開頭
getPrivateProp() {
return this.#privateProp; // 父類內部可訪問私有成員
}
}
class Child extends Parent {
tryAccessPrivate() {
console.log(this.#privateProp); // 報錯:Private field '#privateProp' must be declared in an enclosing class
}
}
const parent = new Parent();
console.log(parent.getPrivateProp()); // 輸出:私有屬性
const child = new Child();
child.tryAccessPrivate(); // 報錯,子類無法訪問父類私有成員
實際開發中的常見場景
class/extends在實際開發中應用廣泛,比如:
-
封裝組件基類:在前端框架中,定義基礎組件類封裝通用邏輯(如生命週期、事件綁定),再通過子類擴展具體組件。
-
工具類設計:定義基礎工具類(如HttpUtil),子類可擴展不同場景的請求邏輯(如UserHttp、OrderHttp)。
-
數據模型封裝:用類定義數據模型(如User、Product),通過繼承實現模型間的屬性複用。
組件基類示例:
// 基礎組件類
class BaseComponent {
constructor(el) {
this.el = document.querySelector(el);
this.bindEvents();
}
// 通用事件綁定邏輯
bindEvents() {
// 子類可重寫該方法,添加自身事件
}
// 通用渲染方法
render(data) {
this.el.innerHTML = this.template(data);
}
// 模板方法:子類必須實現
template(data) {
throw new Error("子類必須重寫template方法");
}
}
// 按鈕組件子類
class ButtonComponent extends BaseComponent {
constructor(el, text) {
super(el);
this.text = text;
}
// 重寫模板方法
template() {
return `="custom-btn">${this.text} }
// 重寫事件綁定
bindEvents() {
this.el.addEventListener("click", () => {
console.log(`${this.text}按鈕被點擊`);
});
}
}
// 使用子類創建組件
const loginBtn = new ButtonComponent("#login-btn", "登錄");
loginBtn.render(); // 渲染按鈕到頁面
class和extends讓 JavaScript 的面向對象編程更貼近其他編程語言的語法習慣,同時保留了 JS 的靈活性。掌握類的定義、實例化、繼承、方法重寫和私有成員等核心知識點,能讓代碼結構更清晰、複用性更強,尤其適合大型項目的模塊化開發。無論是封裝工具類、組件基類,還是設計數據模型,class/extends都是提升代碼質量的重要工具。