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,在讀高二年級
繼承中的注意事項
  1. 子類構造函數中必須先調用****super(),才能使用this關鍵字,否則會報錯。super()的作用是初始化父類的實例屬性,確保子類繼承的屬性正常掛載。

  2. 子類可以重寫父類的實例方法、靜態方法和 getter/setter,重寫後會優先執行子類的邏輯。

  3. 父類的私有成員(用#開頭定義)不會被子類繼承,子類無法訪問。

私有成員與繼承限制示例:

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在實際開發中應用廣泛,比如:

  1. 封裝組件基類:在前端框架中,定義基礎組件類封裝通用邏輯(如生命週期、事件綁定),再通過子類擴展具體組件。

  2. 工具類設計:定義基礎工具類(如HttpUtil),子類可擴展不同場景的請求邏輯(如UserHttp、OrderHttp)。

  3. 數據模型封裝:用類定義數據模型(如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都是提升代碼質量的重要工具。