只看一次絕對學不會的 JavaScript 原型指南(二):建構函式與 prototype 屬性
建構函式的 概念與作用
什麼是建構函式(constructor function)?
在正式介紹 prototype 屬性之前,我們需要先認識與 prototype 屬性密切相關的建構函式(constructor function),這個詞會在本文中多次出現。
在 JavaScript 中,建構函式是一種特殊的函式,用於創建和初始化物件實例。建構函式的主要功能是設置新物件的初始狀態,將屬性和方法賦值給新物件。此外,建構函式通常以大寫字母開頭,以區分於普通函式。
當使用 new 關鍵字來調用函式時,這個函式就被認為是建構函式。以下是建構函式的一般語法:
function Person(name, age) {
this.name = name; // 初始化 name 屬性
this.age = age; // 初始化 age 屬性
// 可以執行其他初始化操作
}
建構函式與普通函式在語法上非常相似,乍看之下可能會分不清兩者之間具體的區別,以下我整理了它們在用途和調用方式上的一 些重要區別:
- 用途:
- 建構函式:主要用於創建新的物件實例,並初始化該物件的屬性和方法。
- 普通函式:執行特定的任務或計算,並返回結果。
- 調用方式:
- 建構函式:使用
new關鍵字來調用,這會自動創建一個新物件,並將this綁定到這個新物件上。 - 普通函式:直接調用,不使用
new關鍵字,this綁定根據調用環境而定。
- 建構函式:使用
以下是兩者的區別範例:
// 普通函式
function greet() {
console.log("Hello!");
}
greet(); // Hello!
// 建構函式
function Person(name, age) {
this.name = name;
this.age = age;
}
let john = new Person('John', 30);
console.log(john.name); // John
建構函式與直接宣告物件的區別
我在學習建構函式時發現一個有趣現象,就是大多數的人平常都不會用建構函式來創建物件,而是用下列這種寫法:
const person = {
name: 'Alice',
age: 30
};
console.log(person.name); // Alice
在知道如何使用建構函式建立物件後不免心裡會產生一些疑問:
哦? 原來物件還能這樣定義啊? 哦? 原來這才是創建物件的正式寫法啊? 難道我一直都寫錯了嗎?
在 JavaScript 中,創 建物件的方式有多種,其中最常見的是使用物件字面量和建構函式。物件字面量是一種簡單直觀的創建物件方式。通過直接定義物件的屬性和值,可以快速創建一個新的物件,如上面的範例所示。
不過,其實在 JavaScript 內部,物件字面量仍然是通過內建的 Object 建構函式來創建物件的。換句話說,當你使用物件字面量創建物件時,JavaScript 引擎會在背後自動使用 Object 建構函式來完成這個過程。
const person = { name: 'Alice', age: 30 };
// 相當於
const person = new Object();
person.name = 'Alice';
person.age = 30;
類似於物件字面量,陣列字面量也是創建陣列的一種簡化方法。通過直接定義陣列的元素,可以快速創建一個新的陣列。同樣地,儘管陣列字面量是一種簡單的創建方式,但在 JavaScript 內部,實際上是使用了內建的 Array 建構函式來創建陣列。
const numbers = [1, 2, 3];
// 相當於
const numbers = new Array(1, 2, 3);
靜態成員與實例成員的差異
在 JavaScript 中,建構函式可以有靜態成員(Static Members) 和實例成員(Instance Members)。
靜態成員是直接定義在建構函式本身上的屬性或方法。這些成員只能通過建構函式本身來訪問,而不能通過實例來訪問。
function Person(name) {
this.name = name;
}
// 定義靜態屬性
Person.species = 'Homo sapiens';
// 定義靜態方法
Person.describeSpecies = function() {
console.log(`All humans belong to the species ${this.species}.`);
};
console.log(Person.species); // 'Homo sapiens'
Person.describeSpecies(); // "All humans belong to the species Homo sapiens."
let alice = new Person('Alice');
console.log(alice.species); // undefined
console.log(typeof alice.describeSpecies); // undefined
實例成員是在建構函式中使用 this 關鍵字定義的屬性或方法。這些成員是特定於每個實例的,必須通過實例來訪問。
function Person(name) {
this.name = name; // 定義實例屬性
this.greet = function() { // 定義實例方法
console.log(`Hello, my name is ${this.name}.`);
};
}
let alice = new Person('Alice');
alice.greet(); // "Hello, my name is Alice."
let bob = new Person('Bob');
bob.greet(); // "Hello, my name is Bob."