請描述下js的原型和原型鏈的理解以及它們之間的關係

王铁柱6發表於2024-11-25

在 JavaScript 中,原型和原型鏈是理解繼承和物件建立機制的核心概念。它們緊密聯絡,共同構成了 JavaScript 的物件導向特性。

1. 原型 (Prototype):

  • 每個 JavaScript 函式都有一個 prototype 屬性,它是一個物件,被稱為函式的原型物件。
  • 當一個函式被用作建構函式(使用 new 關鍵字)建立新物件時,新建立的物件會自動獲得一個內部的 [[Prototype]] 屬性(在瀏覽器中可以透過 __proto__ 訪問,但 __proto__ 已被棄用,建議使用 Object.getPrototypeOf()),該屬性指向建構函式的 prototype 屬性。
  • 原型物件的主要作用是共享屬性和方法。透過原型,多個物件可以共享相同的屬性和方法,而無需在每個物件上單獨建立副本,從而節省記憶體。

2. 原型鏈 (Prototype Chain):

  • 當訪問一個物件的屬性時,JavaScript 引擎首先會在物件自身查詢該屬性。
  • 如果物件自身沒有該屬性,引擎會沿著原型鏈向上查詢。原型鏈是由物件的 [[Prototype]] 屬性連線起來的一系列物件。
  • 查詢過程會一直持續到找到該屬性或者到達原型鏈的頂端 (null)。
  • 原型鏈的頂端是 null,這意味著如果在整個原型鏈上都沒有找到該屬性,則返回 undefined

3. 原型和原型鏈的關係:

  • 建構函式的 prototype 屬性決定了由該建構函式建立的物件的原型。
  • 物件的 [[Prototype]] 屬性指向其建構函式的 prototype 屬性,從而形成了原型鏈。
  • 原型鏈本質上是一個連結串列結構,連線著物件及其原型,最終連線到 null

示例:

function Person(name) {
  this.name = name;
}

Person.prototype.sayHello = function() {
  console.log("Hello, my name is " + this.name);
};

const person1 = new Person("Alice");
const person2 = new Person("Bob");

person1.sayHello(); // Output: Hello, my name is Alice
person2.sayHello(); // Output: Hello, my name is Bob

console.log(person1.hasOwnProperty("name")); // Output: true (name 屬性在 person1 物件自身)
console.log(person1.hasOwnProperty("sayHello")); // Output: false (sayHello 屬性在 Person.prototype 上)
console.log(Object.getPrototypeOf(person1) === Person.prototype); // Output: true (person1 的原型是 Person.prototype)
console.log(Object.getPrototypeOf(Person.prototype) === Object.prototype); // Output: true (Person.prototype 的原型是 Object.prototype)
console.log(Object.getPrototypeOf(Object.prototype) === null); // Output: true (Object.prototype 的原型是 null,原型鏈的頂端)

總結:

原型和原型鏈是 JavaScript 實現繼承和共享屬性的關鍵機制。理解它們的工作原理對於理解 JavaScript 的物件導向特性至關重要。 透過原型鏈,物件可以繼承來自其原型的屬性和方法,從而避免了程式碼冗餘,提高了程式碼的可重用性和效率。

希望這個解釋能夠幫助你理解 JavaScript 的原型和原型鏈。

相關文章