iT邦幫忙

2026 iThome 鐵人賽

DAY 10
0
Modern Web

現代函式庫與JavaScript的關係系列 第 10

Day 10 | 從 JS 底層物件機制看三大框架:從 static/instance 方法到 Property Descriptor 如何塑造 Vue、React 與 Angular

  • 分享至 

  • xImage
  •  

在現代前端開發中,我們每天都在編寫 React.useStateVue ref/reactive 或 Angular 的 @Component 類別。然而,當我們剝離 JSX、模板編譯器(Template Compiler)與 TypeScript 裝飾器(Decorators)這些外衣,前端框架的本質依然運行在 ECMAScript 的物件模型之上。

本文將從 JavaScript 最底層的 靜態方法(Static Methods)實例方法(Instance Methods)存取器屬性(Accessor Properties / Property Descriptors) 出發,縱向剖析這三項語言特性如何深刻影響了 Vue、Angular 與 React 的架構設計與 API 哲學。


一、JavaScript 物件機理:三大底層基石

在深入框架前,我們必須先釐細 JS 物件的三種關鍵行為:

class BaseModule {
  // 1. 實例屬性與實例方法 (Instance Level)
  constructor(name) {
    this.name = name;
  }
  render() {
    return `Rendering ${this.name}`;
  }

  // 2. 靜態方法 (Class/Constructor Level)
  static create(name) {
    return new BaseModule(name);
  }
}

// 3. 存取器屬性 (Accessor Property Descriptor)
Object.defineProperty(BaseModule.prototype, 'status', {
  get() {
    return this._status;
  },
  set(value) {
    this._status = value;
    // 可以在此觸發 Side Effect(如派發更新)
  },
  enumerable: true,
  configurable: true
});

  1. 實例方法(Instance Methods):綁定在 prototype 或實例對象上,依賴 this 上下文與狀態(State)耦合。
  2. 靜態方法(Static Methods):直接綁定在建構函式或類別本體上,無須實例化即可呼叫,強調無狀態(Stateless)與工具屬性。
  3. 存取器屬性(Getter / Setter):利用 Property Descriptor 攔截屬性的讀寫操作,是實現「隱式響應式(Implicit Reactivity)」與「依賴追蹤」的核心機制。

二、三大框架對底層特性的選型與縱向比較

三大框架在設計時,對於這三種 JS 原生機制的採納偏好截然不同,這也決定了各自的心智模型(Mental Model):

1. Vue.js:存取器屬性(Getter/Setter)的極致發揮

Vue 的核心靈魂是 響應式系統(Reactivity System),其演進完美對應了 JS 存取器機制的發展:

  • Vue 2 (Object.defineProperty):在元件初始化時,遍歷 data 物件,將所有屬性轉化為存取器屬性(get 負責依賴收集 depend()set 負責派發更新 notify())。
  • Vue 3 (ES6 Proxy):將存取器屬性升級為物件層級的攔截器(Traps),解決了物件動態新增/刪除屬性無法攔截的問題,但核心依然是利用 Getter/Setter 的副作用攔截
// Vue 響應式簡化示意 (Vue 2/3 的底層邏輯)
function reactive(obj) {
  return new Proxy(obj, {
    get(target, key, receiver) {
      track(target, key); // 依賴收集
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      const oldValue = target[key];
      const result = Reflect.set(target, key, value, receiver);
      if (oldValue !== value) {
        trigger(target, key); // 觸發視圖更新
      }
      return result;
    }
  });
}

  • 心智模型:變數導向(Mutative)。開發者直接修改屬性(count.value++),背後由 Setter 悄悄完成視圖更新。

2. Angular:物件導向與實例方法(Instance Methods)的集大成者

Angular 深受傳統面向物件編程(OOP)影響,高度依賴 ES6 Class 的 實例方法 與 TypeScript 裝飾器(Decorators)

  • 實例方法與依賴注入(DI):Angular 的元件、服務(Service)本質上都是實例化的類別。元件生命週期(如 ngOnInit)即為實例方法。
  • 靜態方法:主要用於模組工廠或指令定義(如 NgModule.forRoot() 這種靜態工廠方法模式)。
@Component({ selector: 'app-demo', template: `...` })
export class DemoComponent implements OnInit {
  private data: string;

  constructor(private apiService: ApiService) {} // 依賴注入

  // 實例方法:綁定元件生命週期與實例狀態
  ngOnInit() {
    this.data = this.apiService.getData();
  }
}

  • 心智模型:類別與實例導向(OOP & Class-based)。極度依賴 this 作用域與實例方法來進行狀態維護。

3. React:靜態思維與純函數(Stateless & Immutability)的純粹主義

React 對於原生 Class 的態度經歷了重大轉變,並最終走向了 純函數與靜態導向

  • 早期 Class Component:繼承自 React.Component,使用實例方法(如 render())與實例屬性(this.state)。
  • 現代 Function Component + Hooks:徹底摒棄了 this 與實例的概念。
  • 靜態 API 設計:React 的核心 API(如 React.createElementReact.memoReact.lazyReact.forwardRef)本質上都是頂層的 靜態工具函數
// React 頂層靜態 API 哲學
const MemoizedComponent = React.memo(function MyComponent(props) {
  // 純函數,每一次 Render 都是獨立的 Closure 狀態快照
  return <div>{props.title}</div>;
});

React 拒絕使用 Object.definePropertyProxy 來做隱式攔截。它要求開發者顯式地調用 setState,並透過 不可變資料(Immutability) 與引用相等性檢查(Object.is)來驅動 Reconciliation(調和過程)。

  • 心智模型:函數式與不可變性(FP & Immutability)。UI = f(state),元件只是沒有實例狀態負擔的純函數。

三、縱向比較表 (Comparison Matrix)

框架 JS 底層核心機制 狀態變更機制 心智模型 程式碼風格
Vue.js Accessor Properties (Proxy / Getter & Setter) 隱式攔截與自動追蹤 (Reactive Mutation) 響應式數據驅動 宣告式 / 數據導向
Angular Class ES6, Instance Methods & Decorators 顯式狀態更新 / Zone.js 異步監聽 / Signals 傳統 OOP 物件導向 類別與實例導向
React Pure Functions, Closure & Static Utilities 顯式不可變更新 (setState, Immutability) 函數式 UI 快照 函數式 (FP)

四、總結:從底層觀念看前端架構選擇

理解了 JS 底層物件機制後,我們就能看清框架設計的本質取捨:

  1. Vue 選擇幫開發者做更多,透過 存取器屬性 抹平了狀態追蹤的手動成本,提供極佳的開發體驗(DX)。
  2. Angular 堅守 OOP 與實例方法,透過強型別與結構化的 Class 規範,為大型企業級應用提供高度一致的架構。
  3. React 擁抱 純函數與靜態思維,將語言層面的控制權(如 Immutable 引用變更)交還給開發者,換取了極高的組合性(Composability)與預測性。

前端框架紛繁複雜,但萬變不離其宗。當你掌握了 JavaScript 的物件模型與底層機制,你就不再只是框架的使用者,而是能洞察設計者思維的 Web Platform 開發者。


上一篇
Day 9 | HOC 高階組件與渲染劫持|反向繼承,以及 Vue / Angular 的對應機制
下一篇
Day 11 | 從記憶體與渲染哲學看 useRef:React、Vue 3 與 Angular 的 DOM 操作與狀態持久化比較
系列文
現代函式庫與JavaScript的關係22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言