JavaScript 中 __proto__ 與 prototype 的差異解析

更新日期: 2024 年 11 月 4 日

觀念快速一覽✍️

prototype 的概念

  • prototype 是函數的屬性,用於建構實例。
  • 當函數被用作建構函數(透過 new),新物件的 __proto__ 指向此 prototype

__proto__ 的作用

  • __proto__ 是物件的內部屬性,用於指向其原型(即父物件)。
  • 透過原型鏈進行屬性查找。

主要差異

  • prototype 是建構函數的屬性,供實例使用。
  • __proto__ 是物件指向其原型的連結。

JavaScript 中 __proto__prototype 的差異解析

在 JavaScript 中,原型(Prototype)概念,是理解物件導向特性和繼承機制的基礎。

兩個相關的重要屬性——prototype__proto__——在 JavaScript 原型鏈的運作中,扮演著關鍵角色。

這兩者雖然看起來類似,但在功能和用途上有著顯著差異。

本文將深入探討這兩者的特性及其作用。

閱讀本文前,建議具備相關概念:初學者指南:JavaScript 中不存在的物件屬性與 __proto__

prototype 是什麼?

在 JavaScript 中,每個函數(包括建構函數)都會自帶一個名為 prototype 的屬性。

這個 prototype 屬性是一個物件,用於存儲所有該建構函數實例共享的方法和屬性。

當我們使用 new 關鍵字來調用建構函數時,JavaScript 會自動將新創建物件的 __proto__ 屬性指向該建構函數的 prototype,這樣該新物件便能夠繼承 prototype 上的屬性和方法。

舉個例子:

function Hero(name, power) {
  this.name = name;
  this.power = power;
}

Hero.prototype.sayHello = function() {
  return `Hello, I'm ${this.name}!`;
};

const hero1 = new Hero('Superman', 'Strength');
console.log(hero1.sayHello()); // 輸出 "Hello, I'm Superman!"

在這段代碼中,Hero.prototype 存有 sayHello 方法。

所有由 Hero 建構函數創建的物件實例(如 hero1)都能夠使用 sayHello 方法,因為 hero1__proto__ 指向了 Hero.prototype

prototype 的特性

  • 只有函數才有 prototype 屬性。
  • prototype 是用來儲存可供所有實例共用的屬性和方法。
  • 透過 new 關鍵字創建的物件,其 __proto__ 指向該建構函數的 prototype

__proto__ 是什麼?

__proto__ 是 JavaScript 中每個物件的內建屬性,它指向創建此物件的建構函數的 prototype

透過 __proto__,JavaScript 實現了原型鏈機制:

當我們訪問物件的屬性或方法時,JavaScript 會首先在物件自身尋找。

若找不到則會沿著 __proto__ 指向的原型鏈向上查找,直到找到所需屬性或方法,或到達原型鏈的頂端(通常是 null)為止。

例如:

const hero2 = new Hero('Batman', 'Stealth');

console.log(hero2.__proto__ === Hero.prototype); // 輸出 true

在這個例子中,hero2.__proto__ 指向 Hero.prototype,因此 hero2 能夠訪問 Hero.prototype 上的 sayHello 方法。

__proto__ 的特性

  • 所有物件都擁有 __proto__ 屬性。
  • __proto__ 是物件指向其原型的連結。
  • JavaScript 透過 __proto__ 建立了原型鏈,用以實現屬性和方法的查找機制。

prototype__proto__ 的差異

雖然 prototype__proto__ 都與 JavaScript 中的原型鏈有關,但兩者的概念與用途卻完全不同:

  • prototype 是函數的屬性,其作用是定義該建構函數的所有實例可以共享的屬性或方法。只有函數才具有 prototype 屬性。
  • __proto__ 是物件的屬性,用來指向創建該物件的建構函數的 prototype。所有物件(包括函數物件)都具有 __proto__ 屬性,用於連接到原型鏈。

為什麼 MyCons.__proto__ !== MyCons.prototype

在 JavaScript 中,函數本身也是一個物件,因此它也有 __proto__ 屬性。

然而,這個屬性並不會指向它的 prototype

MyCons.__proto__ 指向的是 Function.prototype,而 MyCons.prototype 是用於存放它的實例所共享的屬性或方法。

因此,MyCons.__proto__ !== MyCons.prototype

結論

理解 __proto__prototype 的差異是掌握 JavaScript 原型鏈的關鍵。

prototype 為建構函數定義共享的屬性和方法,而 __proto__ 用來指向物件的原型,從而建立原型鏈。

透過這兩個屬性的合作,JavaScript 能夠在原型鏈上查找屬性和方法,並有效地實現物件的繼承。

Similar Posts