Skip to content

2026-05-20

/ 10 分鐘閱讀

/ JavaScript Hard Parts v3

解法二:用原型鏈共享方法,避免記憶體浪費

本章節建議從 物件導向 JavaScript:OOP 的核心目標與原型鏈基礎 開始閱讀

前情提要:在Object Literal、Dot Notation、Object.create:三種建立物件的方式中,我們示範了三種建立物件的方式,但每種都需要手動逐一設定屬性,違反了 DRY 原則。

解法一的缺陷

工廠函式解法雖然可讀性高,但存在一個根本性的記憶體問題:每次呼叫 userCreator 建立新使用者時,increment 等方法都會被完整複製一份存進該物件。若系統有一百個使用者、十個方法,記憶體中就有一千份內容完全相同的函式副本。這完全不符合「高效能」的目標。

核心想法:共用一份函式

理想情況是:所有使用者物件共享同一份 increment 函式。當 JavaScript 在某個使用者物件上找不到 increment 時,它不應該報錯,而是自動去一個集中存放函式的地方查找。

這個「集中查找」的機制,正是原型鏈(prototype chain)

Object.create() 建立原型連結

把所有共用方法統一存在一個物件 userFunctionStore 中,並透過 Object.create(userFunctionStore) 建立新的使用者物件。這樣,newUser 本身是一個空物件,但它與 userFunctionStore 之間存在一條隱藏的原型連結

javascript
function userCreator(name, score) {
    const newUser = Object.create(userFunctionStore);
    newUser.name = name;
    newUser.score = score;
    return newUser;
}

const userFunctionStore = {
    increment: function () {
        this.score++;
    },
    login: function () {
        console.log('Logged in');
    },
};

const user1 = userCreator('Ari', 3);
const user2 = userCreator('Jae', 5);
user1.increment();

Object.create() 做了什麼

Object.create(userFunctionStore) 回傳的永遠是一個空物件。傳入的引數 userFunctionStore 並不會被直接複製進去,而是建立一條隱藏的原型連結,指向 userFunctionStore

當 JavaScript 執行 user1.increment() 時:

  1. user1 上找 increment,找不到。
  2. 沿原型鏈查找,找到 userFunctionStore.increment
  3. 執行該函式。

整個過程中,increment 只有一份,存在 userFunctionStore 裡,所有使用者物件共用它。

複習

在每個使用者物件上各自儲存一份 increment 函式副本,會造成什麼效能問題?

這會因為在每個物件上建立相同函式的重複副本而浪費記憶體空間。 如果有 100 個使用者物件和 100 個函式,記憶體中就會存在 10,000 份函式副本, 完全不切實際。

像 increment 這樣的共用函式,在記憶體中理想上應該存在幾份?

一份。不應在不同物件間複製相同的函式,而應只保留一份, 讓所有物件在需要時都能存取它。

JavaScript 的哪個功能讓物件能夠存取不直接儲存在自身上的函式?

原型鏈(prototype chain)。當在原始物件上找不到屬性或函式時, 它允許 JavaScript 在連結的物件上繼續查找,而不會拋出錯誤。

將物件(例如 userFunctionStore)作為引數傳入 Object.create() 的目的是什麼?

該引數會在新建立的空物件與傳入的物件之間建立一條隱藏的連結(原型連結)。 這讓新物件能透過原型鏈存取傳入物件中儲存的函式, 而那些函式並不會被直接加入新物件中。

當 JavaScript 的直譯器在一個以 Object.create() 建立的物件上找不到 increment 時,會怎麼做?

直譯器不會報錯,而是沿著原型鏈,去連結的物件(即傳入 Object.create() 的那個物件) 上查找該函式。如果在那裡找到,就從那裡執行它。

小測驗

JavaScript 的哪個功能讓物件能夠存取儲存在其他地方的函式,而不需要將函式直接放在物件自身上? 原型鏈(prototype chain)

此文章是 FrontendMasters 上的 The Hard Parts of JavaScript 課程筆記

最後更新時間:

Buy Me A Coffee

系列章節 第 40 篇 / 共 46 篇

0 %
MIT Licensed | Copyright © 2025-present Wen-Hsiu's Blog
Photo by Federica Galli on Unsplash