一、簡介
建構函數是 JavaScript 中用來創建和初始化物件的一種特殊函數。
它像一個「模具」,透過new
關鍵字生成多個相似的物件實例。特點
- 函數名稱通常首字母大寫(慣例,非強制)。
- 使用
new
呼叫時,自動創建新物件並設定this
。new
會在記憶體的堆中分配空間給新物件,每次創建的實例都獨立,佔用不同的記憶體位置。 - 可以定義屬性和方法。
二、基本運作
1.定義建構函數
function Person(name, age) {
this.name = name; // 屬性
this.age = age;
this.sayHi = function() { // 方法
console.log(`Hi, I'm ${this.name}`);
};
}
2.使用 new
創建實例
const person1 = new Person("Alice", 25);
const person2 = new Person("Bob", 30);
console.log(person1.name); // "Alice"
person1.sayHi(); // "Hi, I'm Alice"
console.log(person2.age); // 30
new 做了什麼?
- 創建一個空物件
{}
,並在記憶體中分配獨立空間。 - 將
this
綁定到這個新物件。 - 執行建構函數內的程式碼,設置屬性和方法。
- 自動返回這個新物件(除非手動返回其他東西)。
- 創建一個空物件
實例獨立性:
每個用 new
創建的實例(例如 person1
和 person2
)是獨立的,佔用不同的記憶體位置,互不影響。可以用 person1 === person2
驗證,結果會為 false
)。
三、建構函數的執行過程
function Car(model) {
this.model = model;
this.drive = function() {
console.log(`Driving a ${this.model}`);
};
}
const myCar = new Car("Toyota");
myCar.drive(); // "Driving a Toyota"
步驟:
- 1.
new Car("Toyota")
:- 創建空物件
{}
,分配獨立記憶體空間。 this
指向這個物件。
- 創建空物件
- 2.執行函數:
this.model = "Toyota"
this.drive = function...
- 3.返回物件:
myCar
得到{ model: "Toyota", drive: function }
,獨立於其他實例。
四、建構函數與 class
的關係
ES6 引入 class,其實是建構函數的語法糖。
// 建構函數
function Person(name) {
this.name = name;
}
Person.prototype.sayHi = function() {
console.log(`Hi, I'm ${this.name}`);
};
// Class 寫法
class PersonClass {
constructor(name) {
this.name = name;
}
sayHi() {
console.log(`Hi, I'm ${this.name}`);
}
}
const p1 = new Person("Alice");
const p2 = new PersonClass("Bob");
p1.sayHi(); // "Hi, I'm Alice"
p2.sayHi(); // "Hi, I'm Bob"
差異:
class
是更高階的抽象,內部仍基於原型。class
更直觀,方法自動綁到原型。
五、注意事項
1.忘記 new
如果直接呼叫 Person("Alice")
(不加 new
),this
會指向全域物件(瀏覽器中是 window
),造成錯誤。
function Person(name) {
this.name = name;
}
Person("Alice"); // 無 new
console.log(window.name); // "Alice"(全域污染)
解法:嚴格模式("use strict"
)會報錯,或檢查 this
:
//嚴格模式
"use strict";
function Person(name) {
this.name = name;
}
Person("Alice"); // 報錯:Cannot set property 'name' of undefined
//檢查 this
function Person(name) {
if (!(this instanceof Person)) {
return new Person(name);
}
this.name = name;
}
const p = Person("Alice"); // 即使忘了 new 也沒問題
console.log(p.name); // "Alice"
2. 返回值的影響
正常情況下,new
會返回建構函數創建的物件(this
)。但如果建構函數明確返回一個物件(而不是 undefined
或基本類型),new
會返回這個手動指定的物件,忽略 this。
function Test() {
this.name = "Test";
return { name: "Override" }; // 手動返回物件
}
const t = new Test();
console.log(t.name); // "Override"(而非 "Test")
//對比:
function Test2() {
this.name = "Test";
return "string"; // 返回基本類型
}
const t2 = new Test2();
console.log(t2.name); // "Test"(基本類型被忽略,new 使用 this)