在 JavaScript 中,new 關鍵字是用於創建和初始化物件的核心工具之一。
透過 new,我們可以將一個函式(通常稱作「建構函式」)轉化為一個物件模板,用於生成具有特定屬性或行為的物件。
以下,我們會深入解析 new 關鍵字的運作機制,並說明建構函式如何創建出新的物件。
本文將以一個代碼範例作為例子來解釋 new 的詳細流程,幫助你更好地理解它的工作原理和應用方式。
代碼概述與範例
以下是一段使用 new 關鍵字的代碼示例。
我們會逐步分析這段代碼,以解釋它在每一個步驟中發生了什麼。
// heroCreator 建構函式,用於創建具有 name 和 power 屬性的英雄物件
function heroCreator(name, power) {
// 步驟 1: this 指向新物件 {}
// 步驟 1.5: {}.__proto__ 指向 heroCreator.prototype
this.name = name;
this.power = power;
// 步驟 2: 自動 return this (無需顯式 return)
}
// 使用 new 關鍵字創建新物件
const h1 = new heroCreator('kk', 100);在這段代碼中,我們定義了一個名為 heroCreator 的建構函式。
這個函式接收兩個參數:name 和 power。
當使用 new 關鍵字調用 heroCreator 函式時,JavaScript 會創建一個新物件,並自動設置該物件的 name 和 power 屬性。
接下來我們逐步分析這段代碼的運作原理。
new 關鍵字的工作原理
new 關鍵字執行的過程可以分為以下四個步驟,每一步都有特定的行為:
步驟 1:創建新物件並設置 this 指向新物件
當我們使用 new heroCreator('kk', 100); 調用建構函式時,new 會先創建一個空的物件 {},並將 this 關鍵字指向這個新物件。
這意味著在 heroCreator 函式內部,this 變量的值會自動指向新創建的物件。
這一過程確保了 heroCreator 函式能夠直接修改新物件的屬性。
在這個過程中,我們可以將 this 視為新物件的代表。
因此,當我們在建構函式中賦值時,例如 this.name = name;,實際上是在為新物件添加屬性。
步驟 1.5:設置新物件的 __proto__ 指向建構函式的 prototype
JavaScript 中的每個函式都自帶一個 prototype 屬性。
這是一個物件,包含了所有該建構函式的實例,可以共享的屬性和方法。
new 關鍵字創建新物件後,會自動設置新物件的 __proto__ 屬性,讓它指向建構函式的 prototype。
這樣一來,新物件就可以繼承 heroCreator.prototype 上的屬性或方法。
例如,如果我們在 heroCreator.prototype 上添加一個方法,所有使用 heroCreator 創建的物件都可以訪問該方法:
heroCreator.prototype.getDescription = function() {
return `${this.name} 擁有 ${this.power} 的力量`;
};
// 這樣 h1.getDescription() 就會返回 "kk 擁有 100 的力量"這個步驟建立了 JavaScript 的原型鏈,使所有透過 new heroCreator() 創建的物件能共享 heroCreator.prototype 中定義的行為。
步驟 2:執行建構函式內部代碼
在完成指向新物件的設置後,JavaScript 開始執行建構函式內的代碼。
在這段代碼中,我們看到以下兩行代碼:
this.name = name;
this.power = power;這些代碼的作用是將建構函式接收到的參數 name 和 power 存儲到新物件的 name 和 power 屬性上。例如,在 new heroCreator('kk', 100); 調用中,this.name 會被設置為 'kk',而 this.power 會被設置為 100。此時,我們的新物件已經擁有了 name 和 power 這兩個屬性。
步驟 3:自動返回新物件
在 JavaScript 中,如果建構函式沒有顯式地 return 物件,則 new 關鍵字會自動返回新創建的物件(即 this 所指的物件)。
這也是為什麼在建構函式中不需要 return 語句。
如果我們嘗試手動 return 一個原始值(例如數字或字符串),該返回值會被忽略,JavaScript 還是會返回新物件。
例子解說:使用 new 創建新物件
現在我們來看代碼中的一行:
const h1 = new heroCreator('kk', 100);這行代碼創建了一個名為 h1 的新物件,這個物件具有以下屬性:
h1.name,其值為'kk'h1.power,其值為100
另外,h1 的 __proto__ 指向 heroCreator.prototype。
如果 heroCreator.prototype 上有任何屬性或方法,h1 都可以訪問到,例如 h1.getDescription(),它會返回 "kk 擁有 100 的力量"。
new 的優勢與應用情境
使用 new 關鍵字來創建物件,有以下幾個優勢:
- 物件創建自動化:
使用new關鍵字時,JavaScript 會自動創建物件並設置原型鏈,避免了手動設置屬性和方法的繁瑣操作。 - 共享方法節省內存:
使用prototype共享方法,可以減少每個實例重複的代碼。所有透過new創建的物件都會共享相同的prototype,這意味著節省了內存空間。 - 統一的構造模式:
使用建構函式可以建立一個標準化的模板,用於生成特定類型的物件。這對於大型應用程式來說尤為重要,因為可以確保所有物件的行為一致。
結論
透過 new 關鍵字和建構函式,我們可以輕鬆且一致地創建並初始化具有特定屬性和方法的物件。
這不僅使物件創建過程更加直觀,還能通過原型鏈的設置,實現方法共享和內存節省。
理解 new 的工作原理有助於更靈活地在 JavaScript 中創建和管理物件結構,並且能提升代碼的可讀性和維護性。