切換語言為:簡體
理解 JavaScript 中的原型和原型鏈

理解 JavaScript 中的原型和原型鏈

  • 爱糖宝
  • 2024-06-16
  • 2088
  • 1
  • 0

JavaScript 是一種基於原型的語言,理解原型(prototype)和原型鏈(prototype chain)對於深入掌握 JavaScript 的物件導向程式設計非常重要。本文將詳細解釋什麼是原型、原型鏈以及隱式原型,並透過示例程式碼來展示它們的工作原理。

原型

在 JavaScript 中,每個函式都有一個 prototype 屬性,這個屬性是一個物件,包含了由該函式建立的例項物件的公共祖先。當透過建構函式建立一個物件時,例項物件會繼承建構函式 prototype 物件上的屬性和方法。

// 定義一個建構函式
function Person(name) {
  this.name = name;
}

// 在 Person 的 prototype 上定義一個方法
Person.prototype.sayHello = function() {
  console.log(`Hello, my name is ${this.name}`);
};

// 透過建構函式建立例項物件
const person1 = new Person('Alice');
const person2 = new Person('Bob');

// 呼叫例項物件的方法
person1.sayHello(); // 輸出:Hello, my name is Alice
person2.sayHello(); // 輸出:Hello, my name is Bob

在這個示例中,sayHello 方法被定義在 Person 建構函式的 prototype 上,因此所有透過 Person 建構函式建立的例項物件都可以訪問這個方法。

原型鏈

當我們訪問物件的屬性或方法時,JavaScript 引擎會先在物件自身查詢。如果沒有找到,它會沿著原型鏈向上查詢,直到找到屬性或方法,或者到達原型鏈的頂端 null 為止。這個鏈狀的查詢過程被稱為原型鏈。

// 定義一個建構函式
function Animal(type) {
  this.type = type;
}

Animal.prototype.eat = function() {
  console.log(`${this.type} is eating`);
};

// 定義另一個建構函式,並將其原型設定為 Animal 的例項
function Dog(name) {
  Animal.call(this, 'Dog');
  this.name = name;
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
  console.log(`${this.name} is barking`);
};

// 建立 Dog 的例項
const dog = new Dog('Buddy');

// 呼叫例項物件的方法
dog.eat(); // 輸出:Dog is eating
dog.bark(); // 輸出:Buddy is barking

在這個示例中,Dog 的原型被設定為 Animal 的例項,因此 Dog 的例項物件可以訪問 Animal 原型上的 eat 方法。這個查詢過程就是原型鏈的實際應用。

  理解 JavaScript 中的原型和原型鏈

將程式碼放到瀏覽器我們可以透過控制檯我們可以檢視它的原型查詢過程,直到找到object的隱式原型為空原型鏈的查詢就到頭了

隱式原型

每個 JavaScript 物件都有一個 __proto__ 屬性,這個屬性指向建立該物件的建構函式的 prototype。透過 __proto__ 屬性,可以實現原型鏈的查詢。

// 檢查 dog 物件的隱式原型
console.log(dog.__proto__ === Dog.prototype); // 輸出:true
console.log(Dog.prototype.__proto__ === Animal.prototype); // 輸出:true
console.log(Animal.prototype.__proto__ === Object.prototype); // 輸出:true
console.log(Object.prototype.__proto__ === null); // 輸出:true

在這個示例中,我們可以看到 dog 物件的 __proto__ 屬性指向 Dog 建構函式的 prototype,而 Dog.prototype.__proto__ 指向 Animal.prototype,最終 Animal.prototype.__proto__ 指向 Object.prototypeObject.prototype.__proto__null,表示原型鏈的終點。

所有物件都有原型嗎?

並不是所有的物件都有原型。透過 Object.create(null) 建立的物件沒有原型。

// 建立一個沒有原型的物件
const obj = Object.create(null);

console.log(obj.__proto__); // 輸出:undefined
console.log(Object.getPrototypeOf(obj)); // 輸出:null

在這個示例中,我們建立了一個沒有原型的物件 obj,因此 obj.__proto__undefinedObject.getPrototypeOf(obj) 返回 null

結論

透過理解原型、原型鏈和隱式原型,我們可以更好地掌握 JavaScript 的物件導向程式設計。這些概念幫助我們理解物件之間的繼承關係,以及如何透過原型鏈實現方法和屬性的共享。希望這篇文章和示例程式碼能幫助你更深入地理解 JavaScript 中的原型機制。

最後:

理解 JavaScript 中的原型和原型鏈 

大家可以透過分析一下這張圖來加深印象

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.