深入淺出JavaScript 原型鏈:對象繼承的“隱形鏈條”

深入淺出JavaScript 原型鏈:對象繼承的“隱形鏈條”

在 JavaScript 的世界里,原型鏈(Prototype Chain)是一個核心概念。它如同一條隱形的鏈條,連接著所有對象,使得代碼能夠高效地共享屬性和方法。理解原型鏈,不僅能幫助你寫出更優雅的代碼,還能讓你在調試時快速定位問題。


一、從“繼承”說起:為什么需要原型鏈?

想象一個場景:你正在開發一個游戲,游戲中有無數個角色(比如戰士、法師、弓箭手)。這些角色共享一些基礎能力(如移動、攻擊),但又有各自獨特的技能。如果每個角色都單獨定義這些基礎能力,代碼會變得冗余且難以維護。

原型鏈的作用就是解決這個問題。它通過對象之間的關聯關系,讓所有對象共享一套基礎能力,從而節省內存并提高代碼的可維護性。


二、原型鏈的核心:對象與原型

1. 每個對象都有一個原型

在 JavaScript 中,每個對象(除了 null)都有一個隱式原型__proto__),它指向另一個對象——這個對象就是它的原型。原型本身也是一個對象,因此它也可以有自己的原型,形成一條鏈式結構。

const obj = {};
console.log(obj.__proto__); // 指向 Object.prototype

2. 構造函數的原型(prototype)

每個函數(包括構造函數)都有一個 prototype 屬性,它指向一個對象。當用 new 調用構造函數時,新對象的 __proto__ 會指向這個 prototype

function Person(name) {this.name = name;
}
Person.prototype.sayHello = function() {console.log(`Hello, my name is ${this.name}`);
};const alice = new Person('Alice');
console.log(alice.__proto__ === Person.prototype); // true

3. 原型鏈的形成

當訪問一個對象的屬性或方法時,JavaScript 引擎會沿著對象的原型鏈向上查找,直到找到目標或到達原型鏈的盡頭(null)。

// 原型鏈的結構
alice -> Person.prototype -> Object.prototype -> null

三、原型鏈的工作原理:屬性查找的“接力賽”

1. 屬性查找的流程

當你訪問一個對象的屬性時,JavaScript 會執行以下步驟:

  1. 檢查對象自身:如果屬性存在,直接返回。
  2. 沿原型鏈查找:如果對象自身沒有該屬性,則沿著 __proto__ 向上查找原型對象。
  3. 找到或返回 undefined:直到找到目標屬性或到達原型鏈的盡頭(null)。
function Animal(name) {this.name = name;
}
Animal.prototype.speak = function() {console.log(`${this.name} makes a sound.`);
};const dog = new Animal('Buddy');
dog.speak(); // 輸出 "Buddy makes a sound."

在這個例子中:

  • dog 對象自身沒有 speak 方法。
  • JavaScript 引擎沿著 dog.__proto__(即 Animal.prototype)找到 speak 方法。

2. 動態性:修改原型會影響所有實例

原型鏈的動態性是其強大之處,也是潛在的陷阱。修改原型對象的屬性或方法,所有實例都會受到影響。

// 修改原型上的方法
Animal.prototype.speak = function() {console.log(`${this.name} barks!`);
};dog.speak(); // 輸出 "Buddy barks!"

即使 dog 是在修改前創建的,它也會繼承新的 speak 方法。


四、繼承的實現:從構造函數到 ES6 的 class

1. 構造函數繼承

通過將子類的原型設置為父類的實例,可以實現繼承。

function Parent(name) {this.name = name;
}
Parent.prototype.sayName = function() {console.log(this.name);
};function Child(name, age) {Parent.call(this, name); // 繼承屬性this.age = age;
}
Child.prototype = Object.create(Parent.prototype); // 繼承方法
Child.prototype.constructor = Child;const child = new Child('Lily', 12);
child.sayName(); // 輸出 "Lily"

2. ES6 的 class 語法糖

ES6 的 class 本質上是原型繼承的語法糖,簡化了繼承的實現。

class Parent {constructor(name) {this.name = name;}sayName() {console.log(this.name);}
}class Child extends Parent {constructor(name, age) {super(name); // 調用父類構造函數this.age = age;}sayAge() {console.log(this.age);}
}const child = new Child('DT', 1);
child.sayName(); // 輸出 "DT"
child.sayAge();  // 輸出 1

五、原型鏈的實際應用與注意事項

1. 共享方法,節省內存

通過原型鏈,多個實例可以共享同一個方法,而不是每個實例都保存一份副本。

function Circle(radius) {this.radius = radius;
}
Circle.prototype.getArea = function() {return Math.PI * this.radius ** 2;
};const circle1 = new Circle(5);
const circle2 = new Circle(10);
console.log(circle1.getArea === circle2.getArea); // true

2. 原型鏈的終點:Object.prototype

所有對象的原型鏈最終都會指向 Object.prototype,這是 JavaScript 對象模型的起點。

console.log(Object.prototype.__proto__); // null

3. 避免原型污染

不要在 Object.prototype 上隨意添加屬性或方法,這可能導致所有對象意外繼承這些屬性,引發難以排查的錯誤。


六、總結:原型鏈的本質

原型鏈是 JavaScript 實現對象繼承的核心機制。它通過對象之間的關聯,讓代碼能夠高效地共享屬性和方法。理解原型鏈,不僅能幫助你寫出更高效的代碼,還能讓你在面對復雜的對象關系時游刃有余。

關鍵點回顧:

  1. 每個對象都有原型,原型本身也是一個對象。
  2. 屬性查找沿原型鏈向上進行。
  3. 構造函數的 prototype 是共享屬性和方法的載體。
  4. ES6 的 class 是原型繼承的語法糖。
  5. 動態性共享性是原型鏈的雙刃劍,需謹慎使用。

七、延伸思考:原型鏈與現代 JavaScript

隨著 ES6 的普及,classextends 逐漸取代了傳統的原型鏈寫法,但它們的本質仍是原型繼承。理解原型鏈,能讓你更深入地掌握 JavaScript 的底層機制,并在面對性能優化、框架設計等場景時做出更合理的決策。

原型鏈如同 JavaScript 的“基因鏈”,它讓語言具備了靈活的對象模型。掌握它,你將真正理解 JavaScript 的魅力所在。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/85076.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/85076.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/85076.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LINUX中MYSQL的使用

LINUX中MYSQL的使用 MYSQL的數據類型 bool: 布爾類型 0 或者 1 CHAR: 單字符的字符 CHAR(n):多字節字符 VARCHAR(n):可變長度的字符型 TINYINT : 單字節整型 SMALLINT&#x…

打卡第48天:隨機函數與廣播機制

知識點回顧: 隨機張量的生成:torch.randn函數卷積和池化的計算公式(可以不掌握,會自動計算的)pytorch的廣播機制:加法和乘法的廣播機制 ps:numpy運算也有類似的廣播機制,基本一致 …

學習昇騰開發的第四天--基本指令

1、查看npu當前狀態信息 npu-smi info 2、查看NPU的ID npu-smi info -l3、調用python python3 4、修改用戶名 su - HwHiAiUser 5、查看cann版本 cat /usr/local/Ascend/ascend-toolkit/latest/compiler/version.info 6、刪除文件夾 sudo rm -rf HelloWorld7、在本地環…

vue3 - 自定義hook

自定義hook 簡單點來說就是將人物或者訂單的所有數據和方法放在一個ts文件里面 這樣便于維護 假如一個人只需要管 人物的模塊 那他只需要操作usePerson.ts文件就可以了 //useDog.ts import { ref,reactive} from vue; import axios from axios;export default function(){…

【python】bash: !‘: event not found

報錯 # 2. 測試smplx是否工作(可能不需要chumpy) python -c "import smplx; print(? smplx works!)"bash: !: event not found 分析 這是bash的歷史擴展問題,感嘆號被解釋為歷史命令。用這些方法解決: &#x1f680…

【Python打卡Day47】注意力熱力圖可視化@浙大疏錦行

可視化空間注意力熱力圖的意義: 提升模型可解釋性 熱力圖能直觀展示模型決策的依據區域,破除深度學習"黑箱"困境。例如在圖像識別中,可以看到模型識別"貓"是因為關注了貓耳和胡須區域,識別"禁止通行&qu…

樹狀數組 2

L - 樹狀數組 2 洛谷 - P3368 Description 如題,已知一個數列,你需要進行下面兩種操作: 將某區間每一個數加上 x; 求出某一個數的值。 Input 第一行包含兩個整數 N、M,分別表示該數列數字的個數和操作的總個數。…

YOLOv2 技術詳解:目標檢測的又一次飛躍

🧠 YOLOv2 技術詳解:目標檢測的又一次飛躍 一、前言 在 YOLOv1 提出后,雖然實現了“實時性 單階段”的突破,但其在精度和小物體檢測方面仍有明顯不足。為了彌補這些缺陷,Joseph Redmon 等人在 2017 年提出了 YOLOv2…

JAFAR Jack up Any Feature at Any Resolution

GitHub PaPer JAFAR: Jack up Any Feature at Any Resolution 摘要 基礎視覺編碼器已成為各種密集視覺任務的核心組件。然而,它們的低分辨率空間特征輸出需要特征上采樣以產生下游任務所需的高分辨率模式。在這項工作中,我們介紹了 JAFAR——一種輕量級…

SamWaf 開源輕量級網站防火墻源碼(源碼下載)

SamWaf網站防火墻是一款適用于小公司、工作室和個人網站的開源輕量級網站防火墻,完全私有化部署,數據加密且僅保存本地,一鍵啟動,支持Linux,Windows 64位,Arm64。 主要功能: 代碼完全開源 支持私有化部署…

79Qt窗口_QDockWidget的基本使用

目錄 4.1 浮動窗?的創建 4.2 設置停靠的位置 浮動窗? 在 Qt 中,浮動窗?也稱之為鉚接部件。浮動窗?是通過 QDockWidget類 來實現浮動的功能。浮動窗 ??般是位于核?部件的周圍,可以有多個。 4.1 浮動窗?的創建 浮動窗?的創建是通過 QDockWidget…

UE/Unity/Webgl云渲染推流網址,如何與外部網頁嵌套和交互?

需求分析:用threejs開發的數字孿生模型, 但是通過webgl技術網頁中使用,因為模型數據量大,加載比較慢,且需要和其他的業務系統進行網頁嵌套和交互,使用云渲染技術形成的推流網址,如何與外部網頁嵌…

在Termux中搭建完整Python環境(Ubuntu+Miniconda)

蹲坑也能寫python? ?? 環境準備?? 詳細搭建步驟步驟1:安裝Linux容器工具步驟2:查看可用Linux發行版步驟3:安裝Ubuntu系統步驟4:登錄Ubuntu環境步驟5:下載Miniconda安裝包步驟6:安裝Miniconda? 環境驗證?? 使用技巧?? 注意事項前言:想在吃飯、通勤甚至休息間隙…

EventSourcing.NetCore:基于事件溯源模式的 .NET Core 庫

在現代軟件架構中,事件溯源(Event Sourcing)已經成為一種非常流行的模式,尤其適用于需要高可用性和數據一致性的場景。EventSourcing.NetCore 是一個基于事件溯源模式的 .NET Core 庫,旨在幫助開發者更加高效地實現這一…

Linux下的第一個程序——進度條(命令行版本)

文章目錄 編寫Linux下的第一個小程序——進度條進度條的樣式前置知識回車和換行緩沖區對回車、換行、緩沖區、輸出的測試代碼簡單的測試樣例倒計時程序 進度條程序理論版本基本框架代碼實現 真實版本基礎框架 代碼實現 編寫Linux下的第一個小程序——進度條 在前面的基礎開發工…

【項目】仿muduo庫one thread one loop式并發服務器前置知識準備

📚 博主的專欄 🐧 Linux | 🖥? C | 📊 數據結構 | 💡C 算法 | 🅒 C 語言 | 🌐 計算機網絡 |🗃? mysql 本文介紹了一種基于muduo庫實現的主從Reactor模型高并發服務器框架…

steam報網絡錯誤,但電腦是網絡連接的

steam報網絡錯誤,但電腦是網絡連接的 如: 解決辦法: 關閉電腦防火墻和所有殺毒軟件,然后重新打開steam開代理,可能國內有時候訪問不了 首選1進行嘗試 steam安裝路徑一定要在純英文路徑下 已ok

Vue 組合式 API 與 選項式 API 全面對比教程

一、前言:Vue 的兩種 API 風格 Vue 提供了兩種編寫組件邏輯的方式:組合式 API (Composition API) 和 選項式 API (Options API)。理解這兩種方式的區別和適用場景,對于 Vue 開發者至關重要。 為什么會有兩種 API? 選項式 API&a…

HarmonyOS 應用模塊化設計 - 面試核心知識點

HarmonyOS 應用模塊化設計 - 面試核心知識點 在 HarmonyOS 開發面試中,模塊化設計是必考知識點。本文從面試官角度深度解析 HarmonyOS 應用模塊化設計,涵蓋 HAP、HAR、HSP 等核心概念,助你輕松應對技術面試! 🎯 面試高…

Maven高級學習筆記

分模塊設計 為什么分模塊設計?將項目按照功能拆分成若干個子模塊,方便項目的管理維護、擴展,也方便模塊間的相互調用,資源共享。 注意事項:分模塊開發需要先針對模塊功能進行設計,再進行編碼。不會先將工程開發完畢&…