摘要:譯者注根據定義,沒有原型,并作為這個原型鏈中的最后一個環節。由于這個屬性不標準,因此一般不提倡使用。中用函數獲得一個對象的。
溫馨提示:作者的爬坑記錄,對你等大神完全沒有價值,別在我這浪費生命
在上一篇博文javascript對象不完全探索記錄03:小伙子,你對象咋來的?上篇,中大概說了說在js中,比較好理解的對象創建方式,分別是直接定義/字面量,和調用構造函數
你對象還有原型?在一眾博文及書中,有一個高級/不好看明白的方式,比上面這兩種更收到推崇,那就是大名鼎鼎的原型方式,看到這個詞,我表示不是我謙虛,是真懵逼,啥原型,什么原型,誰的原型?現看看別人給的例子
function Car() { } Car.prototype.color = "blue"; Car.prototype.doors = 4; Car.prototype.mpg = 25; Car.prototype.showColor = function() { alert(this.color); }; var oCar1 = new Car(); var oCar2 = new Car();
源自ECMAScript 定義類或對象 - W3school
別說,還真有那么點眼熟,這種對象名稱,后面跟一個prototype的寫法,一直以來是我一個重要懵逼來源,話說這詞,不就是原型的意思嗎?
prototype
英 [?pr??t?ta?p] 美 [?pro?t?ta?p]
n.
原型,雛形,藍本
哈,在這等著我呢,其實認真一看這句Car.prototype.color = "blue";的語法意思是給Car的prototype的color賦值,翻譯一下就是給Car的原型中的color屬性賦值,所以說是不是能理解為原型也就是prototype是對象的一個屬性呢?還是從頭了解吧
所以你原型是啥?提到原型,就不能不提到javascript中的一個重要的懵逼概念 - 原型鏈
每個對象都有一個私有屬性(稱之為 [[Prototype]]),它持有一個連接到另一個稱為其 prototype 對象(原型對象)的鏈接。該 prototype 對象又具有一個自己的原型,層層向上直到一個對象的原型為 null。(譯者注:Object.getPrototypeOf(Object.prototype) === null; // true)根據定義,null 沒有原型,并作為這個原型鏈中的最后一個環節。源自MDN Web docs - Web技術文檔/javascript/繼承與原型鏈
這段話我注意到的有幾個關鍵詞:每個對象,私有屬性,鏈接,層層向上
用直白的話描述一下,在javascript中任何一個對象都有一個叫做原型對象的對象,這個原型對象就是傳說中的prototype,而指向原型對象的鏈接/指針/箭頭/->/都存在對象內部的一個私有屬性中[[Prototype]]中(*見注1)
也就是說對象的[[Prototype]]中并不是直接存了原型對象,而是存著一個指向原型對象的鏈接//這也就使得其是動態的-待研究
由此可以想到的,既然每個對象都有原型對象,每個對象也都可以作為其他對象的原型對象,那么就會形成一個由[[Prototype]]屬性組成的鏈,這就是傳說中的原型鏈了,而利用原型鏈,對象可以訪問其原型對象的屬性及方法
*注1
[[prototype]]是一個隱藏屬性,但很多瀏覽器都給每一個對象提供.__proto__這一屬性,這個屬性就是上文反復提到的該對象的[[prototype]]。由于這個屬性不標準,因此一般不提倡使用。ES5中用Object.getPrototypeOf函數獲得一個對象的[[prototype]]。ES6中,使用Object.setPrototypeOf可以直接修改一個對象的[[prototype]]源自知乎問題 - js中__proto__和prototype的區別和關系? - 知乎用戶的回答
換句話說,任何一個對象,都是在另一個被叫做原型對象的基礎之上被創建出來的,這也就是所謂的原型了
整這么麻煩干嘛?就像我們知道的,在學園都市里有好多少女們/對象,她們各自有不同名字,頭發顏色,以及超能力,她們可以展現自己的超能力,我們建立一個名叫GirlFriend()的構造函數,來記錄記錄
function GirlFriend(name,hairColor,power){ this.name = name; this.hairColor = hairColor; this.showPower = function(){ console.log(power) } }
記錄/實例化炮姐和黑子
var mikoto = new GirlFriend("Mikoto","brown","BiliBili"); var kuroko = new GirlFriend("Kuroko","black","Telesport"); mikoto.showPower();//BiliBili kuroko.showPower();//Telesport
直到這里一切都很正常,但是卻發現炮姐不是一個人!有人處于某種原因克隆了好多炮姐,如何記錄炮姐的妹妹們呢,我們創建一個構造函數Sister()用于記錄炮姐的妹妹們
function Sister(level,number){ this.level = level; this.number = number; this.showLevel = function(){ console.log(this.level); } }
但是妹妹們也是由炮姐克隆而來的啊,炮姐有的屬性她們也都應該有啊,怎么辦,直接在Sister()里新增屬性嗎?太麻煩了而且這就跟炮姐沒關系了,炮姐哪天要是在GrilFriend()里多錄入一個新的屬性,在Sister()也還得繼續添加。
就沒有什么更好的方式嗎,答案是肯定的
于是我們就用炮姐這個實例對象作為原型對象
Sister.prototype = mikoto;
在這里Sister.prototype指的是由構造函數Sister()生成的實例對象所對應的原型對象
說白了,上面這行代碼的的作用就是讓所有由Sister()生成的實例對象的原型對象都是mikoto,我們來試試結果
var sister = new Sister(3,"0001"); sister.showPower();//BiliBili sister.showLevel();//3
到此為止一個擁有3級BiliBili能力的妹妹就誕生了
而且其整個的執行過程也與我們對鏈的理解一樣,是從內到外,從這兒到那兒的
GirlFriend.prototype.age = 14; console.log(sister);//見截圖 console.log(sister.age)//14
從結果中可以看出,sister對象內部并沒有age屬性,在sister對象的原型對象mikoto中也沒有age屬性,但是在mikoto的原型對象中包含age屬性并且有值,所以sister對象就順著原型鏈一路找到了第一個age屬性
但其實sister的因為是被克隆出來的所以只有1歲而已
sister.age = 1; console.log(sister);//見截圖 console.log(sister.age)//1
從運行結果可以看出,sister對象內部有age屬性,這個是sister原型鏈上第一個age屬性,所以sister.age的值就取1
為由GirlFriend()實例化對象的原型對象增加屬性age并賦值,看看sister.age
在上文代碼和截圖中出現了兩個和prototype相關的詞,prototype和_proto_,這倆貨是干啥的?
其實上文提到了,構造函數Foo()的prototype屬性指的就是這個構造函數所對應的原型對象,其實就是通過Foo()創建的對象的原型對象,所以prototype是構造函數所具有的一個屬性
而_proto_屬性是對應對象所說的,見上文注1所說,舉個例子
sister.__proto__.age = 1 console.log(mikoto.age);//1 console.log(kuroko.age);//14 sister.__proto__.__proto__.age = 1 console.log(kuroko.age);//1
正如例子中表現的,對象可以通過_proto_屬性獲得自己的原型對象,以及原型鏈上每一個對象
在截圖中的原型對象中,還存在一個constructor的屬性,這個屬性指向的就是這個原型對象所對應的構造函數,也就是那個構造出原型對象為該對象的函數,一句話概括就是構造函數和其對應的對象互相擁有彼此,構造函數將對象放在prototype屬性中,對象將構造函數放在constructor屬性中我想這就是愛情吧
這里再放一張圖,就能更清除解釋他們之間的關系了
源自知乎問題 - js中__proto__和prototype的區別和關系? - doris的回答
話說回來繞了這么大一圈,還沒忘我們為什么要研究原型吧,通過原型的方式創建對象的屬性和方法,就可以利用同種對象類型的不同實例擁有想用的原型對象這一特性,避免重復創建,并且在修改原型對象的某個屬性后,也可以通過原型鏈影響到其他所有相關對象上。
舉個例子
GirlFriend.prototype.sayHello = function(){ console.log("Ohayo!") } kuroko.sayHello();//Ohayo! sister.sayHello();//Ohayo!
并且說到底她們執行的都是同一個sayHello()
關于原型這塊概念相對復雜,還設計嵌套,相互引用等等深坑,還是得先捋清楚再自己多做聯系來理解和熟練運用啦
能看到這的估計都懵逼了
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/92275.html
摘要:溫馨提示作者的爬坑記錄,對你等大神完全沒有價值,別在我這浪費生命溫馨提示續本文內容簡單,發揚了潛入潛出的精神,請謹慎浪費時間溫馨提示再續魔卡少女櫻動畫再開撒花經過前兩篇文章的梳理對象不完全探索記錄小伙子,你對象咋來的上篇對象不完全探索記 溫馨提示:作者的爬坑記錄,對你等大神完全沒有價值,別在我這浪費生命溫馨提示-續:本文內容簡單,發揚了潛入潛出的精神,請謹慎浪費時間溫馨提示-再續:《魔...
摘要:這是因為子類沒有自己的對象,而是繼承父類的對象,然后對其進行加工。 溫馨提示:作者的爬坑記錄,對你等大神完全沒有價值,別在我這浪費生命溫馨提示-續:你們要非得看,我也攔不住,但是至少得準備個支持ES6的Chrome瀏覽器吧?溫馨提示-再續:ES6簡直了,放著不用簡直令人發指! 書接上回,即便是程序員,也還是能夠通過自己的努力辛辛苦苦找到合適對象的,見前文《javascript對象不完全...
摘要:看著別人寫的功能對,就直接拿過來用,寫出來的代碼臃腫到爆炸,滿屏幕的的初級使用方式,運氣好了能湊合跑起來,出了問題全臉懵逼,心中安慰自己一萬遍我可是干設計的,但是既然打算好好整下就得從頭開始看了。 溫馨提示:作者的爬坑記錄,對你等大神完全沒有價值,別在我這浪費生命 首先,說實話,我對不起javascript,作為一個接觸前端快10年的老前端(偽),一直發揚的是不求甚解的拿來就用主義。看...
摘要:站在這個時間點上,我對自己之前三次失敗的面試經歷做了一次深度回顧。關于我第三次面試失敗的經歷,依然是與輪播圖有關。當然,這次思特奇面試之旅,最后也是以失敗告終,這也是我離進大廠最近的一次。 showImg(https://segmentfault.com/img/bVYQuP?w=528&h=513); 前言 時間的齒輪已經來到了2017年的11月份,距離2018年僅僅還剩下不到兩...
閱讀 1000·2021-11-22 13:52
閱讀 1441·2021-11-19 09:40
閱讀 3122·2021-11-16 11:44
閱讀 1263·2021-11-15 11:39
閱讀 3893·2021-10-08 10:04
閱讀 5333·2021-09-22 14:57
閱讀 3096·2021-09-10 10:50
閱讀 3177·2021-08-17 10:13