淺談 JavaScript 的原型繼承(Prototype and Inheritance)與原型鏈

更新 發佈閱讀 6 分鐘
JavaScript Object Prototype 示意圖

JavaScript Object Prototype 示意圖

在 JavaScript 中,每個Object(以下稱為物件)都有一個隱含的 [[Prototype]]屬性,它指向這個物件的原型(Prototype)。當試圖訪問物件的某個屬性時,如果這個物件本身沒有該屬性,那麼 JavaScript 引擎會繼續在它的 [[Prototype]] (aka prototype object) 上找這個屬性。這就是 JavaScript 的原型繼承(Prototypal Inheritance)與原型鏈(Prototype Chain)概念

附註:這篇文章提到的 Object 都是以 object literal (object initializer) 來創造,不考慮構造函數與 class 的情況。

Prototype Object 範例

我們先來看看這段程式碼:

const person = {
name: 'John',
sayName() {
console.log(this.name);
}
}

const student = {
school: 'ABC'
};

// 將 person 設置為 student 的 Prototype Object
Object.setPrototypeOf(student, person);

// 訪問 student 的 Prototype Object person 上的 sayName 方法
student.sayName(); // 輸出 John

上面的程式碼中,我們將 person 設置為 student 的 Prototype Object,這樣 student 就可以access到 person 上的屬性和方法,這就是 JavaScript Prototype Object 的作用,實現物件間的繼承與共享


這裡可能有個令人費解的片段:

Object.setPrototypeOf(student, person)

這是 ES6 提供的設定物件原型的方法。它接受兩個參數:第一個參數是要設置原型的物件、第二個參數是該物件的新原型。所以這行程式碼使 student 物件的隱式原型 [[Prototype]] 被設置為 person這個 Object。

這樣一來,當訪問 student 的屬性時,如果 student 不存在該屬性,就會去 person 物件上查找。student 物件就可以 access 到 person 的屬性與方法,實現了原型繼承

看起來很麻煩?為什麼要這樣做?可以繼續往下看,或是跳過這個段落 :


補充:proto屬性:[[Prototype]] & __proto__ 的差别

前面提到:

在 JavaScript 中,每個物件都有一個隱含的 [[Prototype]] 屬性,它指向該物件的 Prototype。

但為什麼在上面的程式碼中我們不直接修改它?這是因為[[Prototype]]是隱含的,無法被我們直接訪問、存取(access)。而__proto__ 可以說是這個隱含屬性的 getter/setter 介面(可以 access)

通過 __proto__ 我們可以設置物件的 Prototype Object:

// 通過 __proto__ 設置 Prototype Object
student.__proto__ = person;

student.sayName(); // John
但這種方式會有瀏覽器兼容性的問題,而且是過時的方式,我們不應該使用這個方法來修改prototype object。Object.setPrototypeOf 是更推薦的設定原型的方式。

新增原型繼承物件最簡單的方法:Object.create()

Object.create() 是 JavaScript 中實現 Prototypal Inheritance 最簡單的方法。

它可以以一個物件為原型,創建一個新的物件。不需要先新增物件後再去修改。可以比較兩種方法:

const person = {
name: 'John'
};

// Object.create() 直接新增一個 student 物件並把他的原型指定為 person
const student1 = Object.create(person);

// Object.setPrototypeOf() 先新增一個 student 物件再將其原型對象指定為 person
const student2 = {};
Object.setPrototypeOf(student2, person);

結果上來說,兩者是幾乎相同的,但在MDN的文件中基於效能考量更建議使用Object.create()的方法而不是Object.setPrototypeOf(student, person)

總結

Prototype 是 JavaScript 的核心概念之一,是實現繼承的基礎。

  • 每個 Object 都有一個內置的 [[Prototype]] 指向 Prototype Object
  • __proto__ 屬性可以訪問這個隱含的 Prototype
  • Prototype Object 可以繼續擁有自己的 Prototype,形成原型鏈(Prototype Chain)
  • Object.create() 可以簡單實現基於原型的繼承
  • 構造函數和類也是基於原型模型實現繼承的。

結語

因為篇幅的關係,這篇文章提到的 Object 都是基於 object literal (object initializer) ,不考慮構造函數與 class 的情況,希望未來還有機會寫一篇相關分享~

如果有興趣,可以參考JS基本觀念: 原型鏈(prototype chain) 有提到更多以構造函數來講解原型鏈的概念,或是直接看MDN的文件:Inheritance and the prototype chain

但因為這篇提到的概念是更底層的邏輯,我想在原理上應該是類似或相同的,只是語法上有所差異。如果喜歡這類的文章歡迎留言跟我說!有任何資訊錯誤也請務必留言告知,謝謝😊

留言
avatar-img
DanielNotes
11會員
12內容數
分享關於自我成長、筆記工具、科技、設計等相關文章
DanielNotes的其他內容
2024/02/05
回顧我具有轉變性的 2023 年,我分享了我出國留學的旅程、個人成長以及無數的第一次經驗。
Thumbnail
2024/02/05
回顧我具有轉變性的 2023 年,我分享了我出國留學的旅程、個人成長以及無數的第一次經驗。
Thumbnail
2024/01/27
最近在 LinkedIn Networking發生了一些有趣的事。對於創業者來說,決心和信任相當重要。創業題目雖重要,但找到優秀的團隊和創辦人更難。執行力和對待團隊的方式也關鍵。展現決心給其他人信任和支持。建議展現願景、執行力、認真對待團隊。
Thumbnail
2024/01/27
最近在 LinkedIn Networking發生了一些有趣的事。對於創業者來說,決心和信任相當重要。創業題目雖重要,但找到優秀的團隊和創辦人更難。執行力和對待團隊的方式也關鍵。展現決心給其他人信任和支持。建議展現願景、執行力、認真對待團隊。
Thumbnail
2023/12/18
無聊逛到 曼努 manzoo 的部落格,學習到很多關於台灣字體的知識!這些充滿古早味的字體都有著自己的故事。󠀠 我自己的體感是,台灣前幾年吹著滿滿的復古風,所以這些在過去被認為很「俗」的字體才能被更多人重視。󠀠
Thumbnail
2023/12/18
無聊逛到 曼努 manzoo 的部落格,學習到很多關於台灣字體的知識!這些充滿古早味的字體都有著自己的故事。󠀠 我自己的體感是,台灣前幾年吹著滿滿的復古風,所以這些在過去被認為很「俗」的字體才能被更多人重視。󠀠
Thumbnail
看更多
你可能也想看
Thumbnail
賽勒布倫尼科夫以流亡處境回望蘇聯電影導演帕拉贊諾夫的舞台作品,以十段寓言式殘篇,重新拼貼記憶、暴力與美學,並將審查、政治犯、戰爭陰影與「形式即政治」的劇場傳統推到台前。本文聚焦於《傳奇:帕拉贊諾夫的十段殘篇》的舞台美術、音樂與多重扮演策略,嘗試解析極權底下不可言說之事,將如何成為可被觀看的公共發聲。
Thumbnail
賽勒布倫尼科夫以流亡處境回望蘇聯電影導演帕拉贊諾夫的舞台作品,以十段寓言式殘篇,重新拼貼記憶、暴力與美學,並將審查、政治犯、戰爭陰影與「形式即政治」的劇場傳統推到台前。本文聚焦於《傳奇:帕拉贊諾夫的十段殘篇》的舞台美術、音樂與多重扮演策略,嘗試解析極權底下不可言說之事,將如何成為可被觀看的公共發聲。
Thumbnail
柏林劇團在 2026 北藝嚴選,再次帶來由布萊希特改編的經典劇目《三便士歌劇》(The Threepenny Opera),導演巴里・柯斯基以舞台結構與舞台調度,重新向「疏離」進行提問。本文將從觀眾慾望作為戲劇內核,藉由沉浸與疏離的辯證,解析此作如何再次照見觀眾自身的位置。
Thumbnail
柏林劇團在 2026 北藝嚴選,再次帶來由布萊希特改編的經典劇目《三便士歌劇》(The Threepenny Opera),導演巴里・柯斯基以舞台結構與舞台調度,重新向「疏離」進行提問。本文將從觀眾慾望作為戲劇內核,藉由沉浸與疏離的辯證,解析此作如何再次照見觀眾自身的位置。
Thumbnail
本文深入解析臺灣劇團「晃晃跨幅町」對易卜生經典劇作《海妲.蓋柏樂》的詮釋,從劇本歷史、聲響與舞臺設計,到演員的主體創作方法,探討此版本如何讓經典劇作在當代劇場語境下煥發新生,滿足現代觀眾的觀看慾望。
Thumbnail
本文深入解析臺灣劇團「晃晃跨幅町」對易卜生經典劇作《海妲.蓋柏樂》的詮釋,從劇本歷史、聲響與舞臺設計,到演員的主體創作方法,探討此版本如何讓經典劇作在當代劇場語境下煥發新生,滿足現代觀眾的觀看慾望。
Thumbnail
《轉轉生》為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,融合舞蹈、音樂、時尚和視覺藝術,透過身體、服裝與群舞結構,回應殖民歷史、城市經驗與祖靈記憶的交錯。本文將從服裝設計、身體語彙與「輪迴」的「誕生—死亡—重生」結構出發,分析《轉轉生》如何以當代目光,形塑去殖民視角的奈及利亞歷史。
Thumbnail
《轉轉生》為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,融合舞蹈、音樂、時尚和視覺藝術,透過身體、服裝與群舞結構,回應殖民歷史、城市經驗與祖靈記憶的交錯。本文將從服裝設計、身體語彙與「輪迴」的「誕生—死亡—重生」結構出發,分析《轉轉生》如何以當代目光,形塑去殖民視角的奈及利亞歷史。
Thumbnail
本章節是一個初級的 TypeScript 教學,主要介紹了 TypeScript 中物件導向程式設計的各種核心概念,包括類別、建構子、存取修飾子、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda 表達式、泛型和反射等。每個概念都通過詳細的解釋和實例代碼來進行深入的介紹。
Thumbnail
本章節是一個初級的 TypeScript 教學,主要介紹了 TypeScript 中物件導向程式設計的各種核心概念,包括類別、建構子、存取修飾子、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda 表達式、泛型和反射等。每個概念都通過詳細的解釋和實例代碼來進行深入的介紹。
Thumbnail
本章節旨在介紹JavaScript中的物件導向編程。內容包括類別(Class)的定義和使用,建構子的作用,以及公開,私有,受保護(Protected)等不同訪問修飾符的概念。此外,還涵蓋了繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型、反射等物件導向的主要觀念。
Thumbnail
本章節旨在介紹JavaScript中的物件導向編程。內容包括類別(Class)的定義和使用,建構子的作用,以及公開,私有,受保護(Protected)等不同訪問修飾符的概念。此外,還涵蓋了繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型、反射等物件導向的主要觀念。
Thumbnail
針對 JavaScript 中的原始型別和隱性轉型進行了詳細的探討
Thumbnail
針對 JavaScript 中的原始型別和隱性轉型進行了詳細的探討
Thumbnail
JS 資料型別分為兩大類,原始型別 (Primitive values) 和物件型別 (Objects)。
Thumbnail
JS 資料型別分為兩大類,原始型別 (Primitive values) 和物件型別 (Objects)。
Thumbnail
在剛開始寫 JavaScript 可能大多數的人不會特別意識到 JavaScript 的型別系統有什麼特別之處,我是在看完 Youtube 上 CS50 的課程,才理解到在不同的程式語言中,會因為語言的特性而有不同的系統,JavaScript 就是偏向比較特別的那一種。
Thumbnail
在剛開始寫 JavaScript 可能大多數的人不會特別意識到 JavaScript 的型別系統有什麼特別之處,我是在看完 Youtube 上 CS50 的課程,才理解到在不同的程式語言中,會因為語言的特性而有不同的系統,JavaScript 就是偏向比較特別的那一種。
Thumbnail
今天會接續介紹 JS ES6 其他新穎的語法,物件解構(Object Destructuring)物件語法強化(Object Literal Enhancement)陣列解構(Array Destructuring)延展運算子(Spread Operator)。
Thumbnail
今天會接續介紹 JS ES6 其他新穎的語法,物件解構(Object Destructuring)物件語法強化(Object Literal Enhancement)陣列解構(Array Destructuring)延展運算子(Spread Operator)。
Thumbnail
這篇文章介紹了JavaScript中的原型繼承和原型鏈的概念。每個JavaScript物件都有一個隱含的[[Prototype]]屬性,它指向物件的原型,並當你試圖訪問一個物件的屬性時,JavaScript引擎會在原型鏈上尋找該屬性,實現原型繼承。
Thumbnail
這篇文章介紹了JavaScript中的原型繼承和原型鏈的概念。每個JavaScript物件都有一個隱含的[[Prototype]]屬性,它指向物件的原型,並當你試圖訪問一個物件的屬性時,JavaScript引擎會在原型鏈上尋找該屬性,實現原型繼承。
Thumbnail
創建物件有時是一個資源密集型和耗時的過程,尤其是當涉及到從資料庫或其他來源初始化物件時。原型模式就是為了解決這種問題🔧,它提供了一種方法,能夠通過複製一個已存在的物件來迅速創建新物件,而不是從頭開始。
Thumbnail
創建物件有時是一個資源密集型和耗時的過程,尤其是當涉及到從資料庫或其他來源初始化物件時。原型模式就是為了解決這種問題🔧,它提供了一種方法,能夠通過複製一個已存在的物件來迅速創建新物件,而不是從頭開始。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News