JavaScript原型:關於對象的深入研究

2021-02-19 前端之巔

原型(prototype)是 JavaScript 中每個對象都包含的一個屬性(除非使用 Object.create(null) 來創建對象)。但是它的內部工作機制鮮為人知。原型屬性的分配機制是一個重要的概念,利用它可以在 JavaScript 中應用繼承。在理解原型之前,你必須了解 對象 的一些基本原理和用法。在本文中,我們將深入探討在對象創建過程中是如何分配原型的,以及為什麼這部分知識非常重要。

本文最初發布於 Aparna Joshi 網站,經原作者授權由 InfoQ 中文站翻譯並分享。

使用任何可用方法創建的所有 JavaScript構造函數(constructor function) 都包含一個屬性。這就是 原型 屬性。這裡很重要的是,原型屬性本身就是一個對象。

構造函數的原型屬性可用於訪問 / 修改方法,以及訪問 / 修改在創建對象時分配的原型對象中存在的其他屬性。

每個原型對象都有一個稱為 構造器(constructor) 的屬性。這個屬性指向構造函數 (Constructor Function) 本身。

function Name(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.fullName = firstName + " " + lastName
}
var jensen = new Name("Jensen", "Ackles");
console.log(jensen);

如果嘗試訪問包含對象 jensen 的所有屬性的 console.log,我們將得到以下結果。

到這裡發生過的事情原理是這樣的:

Name 是一個構造函數。它包含 原型 屬性。

這個原型屬性有一個稱為 constructor 的屬性,該屬性指向 Name 構造函數本身。可以將其他任何屬性(attribute)添加到這個屬性上。

使用 Name 構造器創建新對象 jensen 後,這個對象可以訪問屬於 Name 函數的所有屬性,包括其原型。

可以使用 proto 對象從新對象 jensen 中訪問 Name 構造函數的 原型

由於 原型 本身是一個對象,因此它還包含一個 原型 屬性。這樣就創建了 原型鏈:

https://aparnajoshi.netlify.app/javascript-prototype-inner-workings-of-objects#prototype-chain

一些瀏覽器可以支持通過 proto 對象訪問構造函數的原型。我們不建議在 JavaScript 編程中使用這個特性(該特性是非標準特性,可能無法在所有瀏覽器中都正常使用),但也可以用它在開發過程中快速檢查原型鏈的運行狀況。

proto 的替代方法包括 Object.getPrototypeOf() 或 objectInstance.constructor.prototype。對於上述示例來說,可以通過以下方式使用它來訪問相同的原型屬性:

Object.getPrototypeOf(jensen);
jensen.constructor.prototype;


我們通常是通過某些構造函數來創建對象的。如果未使用任何用戶定義的構造器,則表示該對象是使用 JavaScript 的 Object Constructor(對象構造器) 創建的。這意味著我們創建的任何對象最終都將從 JavaScript 的對象構造器繼承。

看一下下面創建的對象,看看它們的 proto 對象包含哪些內容。

function Fruit() {
    this.value = 10;
    this.quantity = 35;
}
function Apple(name, color) {
    this.name = name;
    this.color = color
}
Apple.prototype = new Fruit();
var apple1 = new Apple("Apple", "Red");
console.log(apple1);

如果我們檢查對象 apple1 的內部屬性,則可以觀察到以下內容:

對象 apple1 包含兩個主要屬性:name 和 color。這些屬性的值與在創建過程中分配給它們的值是一樣的。

對象 apple1 的 proto 屬性指向 Fruit 對象的實例。反過來,這又包含另外兩個屬性:value 和 quantity。

如果檢查 Fruit 實例的 proto 屬性,我們會發現它最終指向 JavaScript 的 Object 的原型。

當一個屬性不直接存在於一個對象上時,JavaScript 會沿著 原型鏈 向上尋找,以在其最近的原型中找到該屬性。就像 JavaScript 的作用域鏈一樣,原型鏈也會不斷上升,直到到達 Object.prototype 為止。

原型在 JavaScript 中廣泛用於實現繼承。傳統上,JavaScript 僅用於腳本編寫,並且不需要像其他語言一樣提供面向對象的編程特性。但是,原型的概念可用來將方法和屬性從一個構造函數傳遞到另一個構造函數。

function Fruit() {
    this.value = 10;
    this.quantity = 35;
}
Fruit.prototype.setValue = function(value) {
    this.value = value;
}
function Apple(name, color) {
    this.name = name;
    this.color = color
}
Apple.prototype = new Fruit();
var apple1 = new Apple("Apple", "Red");
apple1.setValue(20);
console.log(apple1.name); // Apple
console.log(apple1.value); // 20
console.log(apple1.quantity); // 35

在上面的示例中,即使新對象 apple1 不具有 value 和 quantity 屬性,我們仍然可以訪問它們。需要注意的是,添加到 Fruit 構造函數 的原型屬性上的 setValue 方法也可以通過對象 apple1 訪問。這就是在 JavaScript 中實現繼承的方式。

使用任何構造器創建對象時,它都會附帶某些可應用於對象的內置方法。其中一些內置方法包括 hasOwnProperty()、isPrototypeOf()、propertyIsEnumerable()、toLocaleString()、toString() 和 valueOf()。這些內置方法可用於所有對象。這是因為 JavaScript 中的所有對象都從 Object.prototype 繼承屬性和方法。

所有內置的構造器,例如 Array()、Number() 和 String() 等,都是從 JavaScript 的 Object 構造器創建的,並且它們的原型也分配給 Object.prototype

JavaScript 中的原型有很多用途,它可用於繼承父函數的方法,還可以用於抽象數據層,並僅公開 getter 和 setter 方法來操作屬於各種對象的值。但原型也有其缺點。原型對象上添加的所有屬性,對於使用其 構造函數 創建的對象的每個實例都是通用的。對於其中任一屬性的任何更改都將反映在所有對象中。

function Apple(name, color) {
    this.name = name;
    this.color = color
}
Apple.prototype.value = 20;
var apple1 = new Apple("Apple", "Red");
var apple2 = new Apple("Apple2", "Wheatish Red");
console.log(apple1.name); // Apple
console.log(apple1.value); // 20
console.log(apple2.value); // 20
Apple.prototype.value = 40;
console.log(apple1.value); // 40
console.log(apple2.value); // 40
apple1.value = 30;
console.log(apple1.value); // 30
console.log(apple2.value); // 40

在上面的示例中,直接在構造器原型上進行的更改會反映在其所有對象中;但是,當更改對象 apple1 內部的屬性 value 時,這一更改就不會反映在其他對象中。這是因為 apple1 現在已經創建了自己的屬性 value,並且從這個實例開始,apple1.value 將始終引用為其自身的屬性 value,而不是繼承的屬性。

為了解決這個問題,可以實現一個 構造器 - 原型 模式的組合。可以使用 構造函數 讓屬於該對象的數據值保持私有和唯一。那些可在所有對象之間共享的操作數據通用方法,可以添加到 原型對象 上。

我希望這篇文章能夠幫助讀者詳細了解原型屬性及其用法。如果你對本文中描述的概念有任何疑問,請隨時與我聯繫:

https://twitter.com/aparna_joshi_

https://aparnajoshi.netlify.app/javascript-prototype-inner-workings-of-objects

相關焦點

  • 2015:JavaScript 之於物聯網
    你可以通過一個類似於手機App的增強現實界面來觀察結果, 或者是基於該界面通過直觀的、無限制的方法去控制這些物聯網設備,而不是直接通過物理的方式去操控對象。有關OpenHybrid的演講[5]:一個關於OpenHybrid背後相關的創意及構建過程的演講。三星的IoT.js和JerryScript
  • 奇怪的JavaScript:map和parseInt的反常應用
    這是因為字符串對象「hello world」是真。每個 JavaScript 對象要麼是真,要麼是假。當將它們放到布爾上下文中時,如放在 if-else 語句中,對象將根據其真實性被視為 true 或 false。那麼哪些對象是真,哪些是假呢?這裡有一個簡單的規則:除了 false、0、「」(空字符串)、null、undefined、及 NaN 以外, 所有值都是真。
  • 【要聞】林小明深入土橋鎮開展遍訪貧困對象行動
    10月20日,市委副書記、市長林小明在市政府辦、市扶貧開發服務中心、長春市生態環境局榆樹市分局、市應急管理局等部門領導的陪同下,深入到土橋鎮開展遍訪貧困對象行動。  林小明一行先後深入到土橋鎮雙羊村、古井村、忠厚村、保家村和光復村,詳細了解了村供水站日常管理、衛生室作用發揮以及扶貧產業發展和貧困戶分紅情況,聽取了負責人對相關情況的匯報。
  • 榮格原型:你有什麼不為人知的隱藏面?
    對於我們潛意識層面的人格表現,著名心理學家卡爾榮格,曾提出「原型」的概念,幫助我們理解深層的自我。他認為,全世界人類的集體潛意識中,存在著十二種人格原型,每個人的主導原型和分類佔比不同。;但如果無法區分真正的愛、和盲目奉獻,他們就會陷入火坑;而【戰士】和【統治者】原型的人,通常表現得很有競爭心、很激進,旁人可能會說他們太過急功近利,但沒關係,那就是他們的節奏,他們有自己的戰場……以上,每種人格原型本身沒有好壞,但如果我們不了解自己的原型,人生的很多路口便會躊躇糾結,狹隘的意識便會束縛我們、幹擾我們選擇。
  • 研究發現:咖啡能讓甜食變得更甜!
    為了測試咖啡對人嗅覺和味覺的影響,研究團隊招攬了156名研究對象。在進行基礎味覺和嗅覺靈敏度測試之後,實驗對象需要飲用一杯溫的意式濃縮咖啡,之後再喝一杯純淨水清理口腔,再進行第二次嗅覺和味覺測試。結果顯示,測試對象的嗅覺靈敏度沒有變化,但其對甜味的味覺靈敏度有所增強。
  • 中國醫學家加強極端環境下人類生存研究
    中國醫學家加強極端環境下人類生存研究 央視國際 www.cctv.com  2006年12月09日 16:58 來源:   新華網西寧12月9日電(記者文貽煒 鄭瑋娜 譚劍)周玉成,心臟搭有五個支架,十次登上海拔5000多米的風火山
  • 測一測:你內心的英雄原型是哪個神話人物?
    所以,挖掘自己內在隱藏的、獨一無二的英雄原型,讀懂自己的使命和人生課題,是每個人需要做的功課:愛神的使命,是學會愛人;西西弗斯的使命,是尋找你所熱愛之事;普羅米修斯的使命,則是尋找勇氣;.比如珂珂,她的內在英雄原型就是象徵著無畏的【普羅米修斯】。
  • 【關注】最高檢:將殘疾人等四類人群作為國家司法救助重點對象
    今年4月起到12月底,全國檢察機關將統一開展「深入推進國家司法救助工作」專項活動。
  • Lancet:前瞻性研究首次表明淋巴絲蟲病可明顯增加HIV的感染風險
    在過去的十年裡,關於蠕蟲誘導的免疫激活是否會影響對HIV易感的個體一直存在爭議。
  • 和相親對象聊天技巧 搞定相親對象指日可待
    怎麼和相親對象聊天?
  • 你贊成放開人類胚胎基因研究的限制嗎?
    央視新聞客戶端10月6日消息,北京時間10月6日,中科院廣州生物醫藥健康研究院裴端卿研究員與九位國際知名學者聯合發表了關於人類胚胎基因編輯的新論述
  • 被問緋聞對象黃遠 林予晞鬆口:屬於可發展的對象
    溫馨提示:點擊上方"藍色字體"↑關注我們歡迎投稿、爆料 請聯繫QQ:74010商務贊助 請聯繫QQ:80002230   80004519被問緋聞對象黃遠是否同去度假,林予晞笑說這趟主題是「閨蜜愛旅行」,黃遠不算在閨蜜組合裡,「他屬於可以發展的對象!」
  • 科普:這些賤萌表情的原型都是誰?
    今天給大家科普一下,在網上常見的那些賤表情,原型都是誰。第一名自然是金館長了,賤表情至少有一半是以金館長的這表情為原型PS出來的。原圖是這樣↓右下角的表情是原型這似笑非笑的表情想嚇死爹啊!要笑為什麼不笑開一點啊!這破玩意誰買啊!
  • 傳蘋果汽車已開始原型研發:拼顏值?
    而最新的聘用活動則暗示其正致力於開發原型車部件。傳蘋果汽車已開始原型研發(圖片來自騰訊)    蘋果最新聘用的人員包括前特斯拉員工David Masiukiewicz等人,他在本月加盟蘋果公司,擔任其產品實現實驗室的高級模型製作人,該公司通過這個實驗室為許多產品製作原型。
  • 中國愛滋病疫苗明年或開啟III期試驗,俄已研發出愛滋病原型疫苗
    中疾控首席愛滋病專家邵一鳴在採訪中表示,愛滋病疫苗是人類面臨的難度最高的科學課題之一,必須加大愛滋病疫苗研究的力度。同時,他指出疫苗只是愛滋病防治的眾多手段之一,抗擊愛滋病必須通過綜合預防和治療措施。俄已研發出愛滋病原型疫苗12月1日是世界愛滋病日。當天俄羅斯聯邦消費者權益保護和公益監督局局長波波娃在莫斯科透露,俄羅斯已研發出愛滋病原型疫苗。
  • 西方學術界關於綏靖政策的研究!!
    西方學術界關於綏靖政策的研究:西方學術界對綏靖政策的研究始於20
  • 【毀三觀】意歷史學家稱蒙娜麗莎原型或為中國女奴
    他更大膽推測,這名中國女奴就是達文西曠世巨作《蒙娜麗莎》(Mona Lisa)的原型。據報導,這位歷史學者名為帕拉提科(Angelo Paratico)。他近20年來都在香港生活及工作,並且研究他的祖國義大利跟中國近五百年來的淵源。根據他的研究,達文西的母親是一名來自東方的女奴。帕拉提科解釋稱,達文西的父親有一名富商客戶,該客戶擁有一位名叫「卡特琳娜」的女奴。
  • 「賭神高進」原型,16歲橫掃賭場,玩牌習慣在賭桌上擺一橙子
    賭博其實是一項非常讓人上癮的活動,今天要給大家介紹的就是關於賭博的重要人物賭神,相信很多人都看過賭神這部劇,並且對賭神的主人公周潤發所飾演的高進是特別的喜歡
  • Momo原型人偶早銷毀
    「Momo挑戰」惡作劇近來在世界各地引起恐慌,恐怖女孩Momo的創造者、日本藝術家相蘇敬介4日表示,原型人偶早被他銷毀,他無意傷害任何人,「孩子可以安心,Momo死了,它不存在了,他告訴法新社,雙眼突出、表情猙獰、笑容詭異的Momo女孩以日本妖怪「產女」(ubume)為發想原型,在日本傳說中,產女是由難產而死的孕婦變成。     相蘇敬介強調,他創造Momo女孩時,並沒有傷害任何人的意圖。Momo女孩於2016年初登場,參加當年在東京銀座區舉行的鬼怪主題展覽,當時這個以矽膠製成、身高約一米的女孩並未受矚目。對相蘇敬介來說,Momo也不過是他手下眾妖之一。
  • 漲姿勢丨關於日本的白色情人節,你知道多少?
    這些男性不僅包括戀人或想要表白的對象,也包括男同事、男同學等。這些巧克力也頗有講究~!根據對象不同,送出的巧克力的名稱也不同。比如,送給自己心儀對象的叫「本命巧克力」,送給其他異性的就叫「義理巧克力」。 那白色情人節又是怎麼回事呢?商家策劃?