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 能夠在原型鏈上查找屬性和方法,並有效地實現物件的繼承。