文章目錄
- 一、構造函數實例化對象
- 1、基本語法
- 2、構造函數與原型的關系
- 3、完整的原型鏈
- 4、構造函數的特點
- 5、`prototype`與`__proto__`屬性
- 5.1、對象實例的`__proto__`屬性
- 5.2、`prototype`屬性僅存在于函數對象
- 5.3、實例與原型的關系
- 5.4、獲取對象原型
- 6、注意事項
前言:
在 JavaScript 里,構造函數是創建對象實例的一種方式。構造函數本質上是普通的函數,不過有其特定的使用模式:要用
new
關鍵字來調用,這樣才能創建對象實例。下面為詳細介紹構造函數實例化對象的相關內容。
一、構造函數實例化對象
1、基本語法
使用構造函數創建對象實例,需要遵循以下步驟:
- 定義一個構造函數,函數名一般首字母大寫(這是約定俗成的寫法,并非強制要求)。
- 在構造函數內部,通過
this
關鍵字來設置對象的屬性和方法。 - 使用
new
關鍵字調用構造函數,從而創建對象實例。
下面是一個簡單的例子:
// 定義一個構造函數
function Person(name, age) {this.name = name;this.age = age;this.sayHello = function() {console.log(`你好,我是${this.name},今年${this.age}歲了。`);};
}// 使用new關鍵字創建對象實例
const person1 = new Person('張三', 25);
const person2 = new Person('李四', 30);// 調用對象的屬性和方法
console.log(person1.name); // 輸出: 張三
person2.sayHello(); // 輸出: 你好,我是李四,今年30歲了。
2、構造函數與原型的關系
當使用
new
關鍵字調用構造函數時,會按照以下步驟執行:
- 首先創建一個新對象。
- 讓這個新對象的
[[Prototype]]
(即原型)指向構造函數的prototype
屬性。 - 將構造函數的
this
綁定到新創建的對象上。 - 執行構造函數內部的代碼,這樣就可以為新對象設置屬性和方法。
- 如果構造函數返回了一個對象,那么就返回該對象;否則,返回新創建的對象。
3、完整的原型鏈
一個典型的原型鏈如下所示:
實例對象 -> 構造函數.prototype -> Object.prototype -> null
驗證方法:
persona1.__proto__ === Person.prototype; // true
Person.prototype.__proto__ === Object.prototype; // true
Object.prototype.__proto__ === null; // true
4、構造函數的特點
- 屬性和方法的復制:每次通過構造函數創建對象實例時,都會為每個實例復制一份屬性和方法。就像上面例子中的
sayHello
方法,每個實例都有自己獨立的副本。 - 原型鏈繼承:所有通過同一個構造函數創建的對象實例,都會繼承構造函數
prototype
屬性上的方法和屬性。
下面通過代碼說明原型鏈繼承:
function Car(make, model) {this.make = make;this.model = model;
}// 給構造函數的prototype添加方法
Car.prototype.getInfo = function() {return `這是一輛${this.make} ${this.model}。`;
};// 創建對象實例
const car1 = new Car('豐田', '卡羅拉');
const car2 = new Car('本田', '思域');// 調用原型上的方法
console.log(car1.getInfo()); // 輸出: 這是一輛豐田 卡羅拉。
console.log(car2.getInfo()); // 輸出: 這是一輛本田 思域。
5、prototype
與__proto__
屬性
5.1、對象實例的__proto__
屬性
在 JavaScript 中,對象實例本身沒有
prototype
屬性,但有__proto__
屬性(非標準,對應內部的[[Prototype]]
)。以下是詳細說明:
- __proto__(非標準):指向該對象的原型對象。
- [[Prototype]](標準):內部屬性,實際決定原型鏈。
const obj = {};
console.log(obj.prototype); // undefined(實例沒有prototype屬性)
console.log(obj.__proto__ === Object.prototype); // true
5.2、prototype
屬性僅存在于函數對象
每個函數默認有一個
prototype
屬性,指向其原型對象:
function Person() {}
console.log(Person.prototype); // { constructor: ? Person() }// 驗證函數也是對象,其原型是Function.prototype
console.log(Person.__proto__ === Function.prototype); // true
5.3、實例與原型的關系
當使用
new
創建對象時,實例的__proto__
指向構造函數的prototype
:
function Person() {}
const alice = new Person();console.log(alice.__proto__ === Person.prototype); // true
console.log(Person.prototype.constructor === Person); // true
5.4、獲取對象原型
推薦使用標準方法
Object.getPrototypeOf()
獲取對象原型:
const obj = {};
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true
6、注意事項
- 忘記使用
new
關鍵字的問題:如果在調用構造函數時忘記使用new
關鍵字,this
會指向全局對象(在瀏覽器環境中是window
對象),這可能會導致意外的結果。為了避免這種情況,可以使用箭頭函數或者在構造函數內部檢查this
是否是當前構造函數的實例。 - 性能方面的考慮:如果構造函數內部定義了大量方法,每個對象實例都會擁有這些方法的獨立副本,這會造成內存的浪費。通常的做法是將共享的方法定義在構造函數的
prototype
上。