摘要:的隱式原型是母,母是由構(gòu)造函數(shù)構(gòu)造的,但函數(shù)的隱式原型又是。。。??赡苁强紤]到它也是由構(gòu)造函數(shù)生成的吧,所以返回的值也是。
首先,我們暫且把object類型和function類型分開來,因?yàn)?function是一個(gè)特殊的對(duì)象類型,我們這里這是便于區(qū)分,把function類型多帶帶拿出來。順便一提,typeof也是多帶帶把function設(shè)為一種類型,我們可以用typeof來驗(yàn)證我們的猜想。
從上圖中可以看到,所有的橘色箭頭(constructor)都指向function Function(){},所有的黑色箭頭(__proto__)開始有兩條路可以走,但是最后都匯聚在了一起,指向null。而天藍(lán)色箭頭(prototype)不具有連續(xù)性,一般都是一個(gè)function指向一個(gè)object。然后我們可以得出以下結(jié)論:
所有對(duì)象的構(gòu)造函數(shù)(constructor)最終指向function Function( ){ }這個(gè)函數(shù),包括他自己。ps:為了方便,我們稱它為母Function。
所有對(duì)象的__proto__最終指向null,即一切原型鏈的末端就是null。
所謂的一切源于對(duì)象,這里的”對(duì)象”指的是Object{}(紅色虛線框內(nèi),也就是Object的prototype)。ps:為了方便,我們?cè)谶@里叫它母Object。
除了Object的原型(prototype)直接指向母Object,其他所有類型的(構(gòu)造器的)原型(prototype)都先指向一個(gè)由母Object派生出來的一個(gè)子Object,再指向母Object,F(xiàn)unction的原型為function{}。ps:構(gòu)造器,即構(gòu)造函數(shù)。
哲學(xué)部分:這幅圖包含兩個(gè)”先有雞還是先有蛋”的問題:
function(){}是由母Function構(gòu)造的,但它同時(shí)又是母Function的原型。。
function(){}的隱式原型(__proto__)是母Object,母Object是由構(gòu)造函數(shù) function Object(){}構(gòu)造的,但函數(shù)function Object(){}的隱式原型又是function (){}。。。。
當(dāng)然除了”先有雞還是先有蛋”,原型鏈中還有一個(gè)最最有哲理的問題:
構(gòu)造函數(shù)function Function(){}的構(gòu)造函數(shù)就是他自己,就是說,他自己把自己生下來了。。。。。 = =
至于為什么function(){}有倆個(gè)框框,其實(shí)是因?yàn)樗窃椭凶钐厥獾?。它是原型中唯一一個(gè)的function類型的,其他的原型都是object類型??赡苁强紤]到它也是由構(gòu)造函數(shù)Function生成的吧,所以typeof返回的值也是function。
我們?cè)賮碚f一下可能大家都很疑惑的問題,就是原型(prototype)和隱式原型(__proto__)的區(qū)別。
我說一下我的見解。相對(duì)于”原型”,我覺得”__proto__”更適合叫做父對(duì)象,因?yàn)樵谠玩溨校?fù)責(zé)連接各個(gè)對(duì)象的,就是”__proto__”。也就是說,我改寫對(duì)象的”prototype”,并不會(huì)影響對(duì)象在原型鏈中的位置,想脫離或者改變?cè)玩?,只能是改寫”__proto__”。
在原型鏈中,對(duì)象和它的”__proto__”指向的對(duì)象的關(guān)系,更像是別的語言中的子類和父類。子類會(huì)繼承父類的方法和屬性,而且會(huì)和父類保持一樣的類型。
一般來說,”__proto__”都是指向某一個(gè)對(duì)象的”prototype”屬性,所以對(duì)象會(huì)繼承的也就是其父對(duì)象”prototype”中的屬性和方法,但是并不會(huì)繼承其父對(duì)象自身的屬性方法。說的可能有點(diǎn)繞,我們舉個(gè)栗子:
//以O(shè)bject為原型創(chuàng)建一個(gè)對(duì)象,obj。 var obj=new Object /*這句話可以翻譯為: var obj={} obj.__proto__=Object.prototype */
這個(gè)時(shí)候,obj的”__proto__”指向的是Object.prototype,所以obj的父對(duì)象是Object.prototype,obj會(huì)繼承Object.prototype中的屬性方法,但是并不會(huì)繼承Object中的屬性和方法。這時(shí)候我們用obj.toString()是可以的,但是用obj.length就會(huì)報(bào)錯(cuò)。這是因?yàn)閠oString()是寫在Object.prototype里面的,而length是寫在Object里面的。
在學(xué)習(xí)運(yùn)算符的時(shí)候,相比很多初學(xué)者也會(huì)有和我一樣的疑問,為什么instanceof向上查找會(huì)在prototype里查找,而不在”父對(duì)象”中查找。理解我上面所說,大家相比也會(huì)明白了吧。就拿上面的例子來說,其實(shí)Object只是obj的構(gòu)造器,構(gòu)造函數(shù)而已,obj真正的父對(duì)象是Object.prototype。
那講到這里有的小伙伴就會(huì)有疑問了,那我要是想繼承Object里面的屬性怎么辦?其實(shí)也很簡單,設(shè)置obj的”__proto__”指向Object就可以了。不過有一點(diǎn),”__proto__”屬性畢竟是底杠開頭,是官方不想暴露在外面的屬性,能不用的時(shí)候最好不要用。其實(shí)就算不用”__proto__”也是可以達(dá)到想要的效果的。Object里面有一個(gè)可以創(chuàng)建對(duì)象的方法create,用它我們可以輕松達(dá)到我們的要求。舉個(gè)栗子:
//以O(shè)bject為原型創(chuàng)建一個(gè)對(duì)象,obj。 var obj= Object.create(Object) /*這句話可以翻譯為: var obj={} obj.__proto__=Object 再說一下create的用法: Object.create(prototype,[{code}]);//返回一個(gè)對(duì)象 可以看到,這里有兩個(gè)參數(shù),第一個(gè)參數(shù)prototype相當(dāng)于創(chuàng)建對(duì)象的__proto__,值得話隨便一個(gè)對(duì)象就可以了,第二個(gè)參數(shù)可以不填,里面詳細(xì)寫創(chuàng)建對(duì)象的一些屬性和他們的屬性標(biāo)簽。注意,create創(chuàng)建的是一個(gè)對(duì)象,和new一樣,無論以什么為父對(duì)象,返回值都是object。 */
再來說說prototype,通過上圖大家會(huì)發(fā)現(xiàn),prototype屬性只是一個(gè)函數(shù)和一個(gè)對(duì)象之間的一個(gè)橋梁,在這里為什么要說是橋梁呢,為什么不說是函數(shù)的一個(gè)屬性呢?我曾寫過一個(gè)例子:
function fa(){} fa.prototype.fname=’fa’ var ch=new fa() ch.fname //’fa’ fa.prototype={fname:’newfa’} //改寫prototype ch.fname //依舊是’fa’, ch.hasOwnProporty(‘fname’) //false ch.__proto__==fa.prototype //false
通過上述代碼大家可以看出來了吧,ch繼承fa時(shí)只是讓ch.__proto__指向了fa.prototype指向的地址,而不是指向fa.prototype。所以就導(dǎo)致了改寫fa.prototype并不會(huì)影響ch.fname的值。改寫后ch.__proto__不等于fa.prototype了,也就是說ch和fa已經(jīng)半毛錢關(guān)系都沒有了。
基本上到這里,大家都會(huì)對(duì)原型鏈有一定的認(rèn)識(shí)了,至于對(duì)象中的特殊存在——function,大家可以自己去探索一下。以上都是自己對(duì)于JS中原型鏈的認(rèn)識(shí),如有錯(cuò)誤歡迎大家指正~
ps:sf的編排好難用 !
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/79872.html
摘要:構(gòu)造函數(shù)的屬性指向原型對(duì)象原型對(duì)象的屬性指向構(gòu)造函數(shù)實(shí)例對(duì)象的指向原型對(duì)象所有引用類型默認(rèn)都繼承了,而這個(gè)繼承也是通過原型鏈實(shí)現(xiàn)的。第一種方式是使用操作符,只要用這個(gè)操作符來測試實(shí)例與原型鏈中出現(xiàn)過的構(gòu)造函數(shù),結(jié)果就會(huì)返回。 理解對(duì)象 首先對(duì)象的定義是:無序?qū)傩缘募希鋵傩钥梢园局?、?duì)象或者函數(shù)。嚴(yán)格來講,這就相當(dāng)于說對(duì)象是一組沒有特定順序的值。對(duì)象的每個(gè)屬性或方法都有一個(gè)名...
摘要:不過,從編程習(xí)慣上,我們應(yīng)該盡量讓對(duì)象的指向其構(gòu)造函數(shù),以維持這個(gè)慣例總結(jié)原型和原型鏈?zhǔn)菍?shí)現(xiàn)繼承的一種模型原型鏈?zhǔn)强啃纬傻模谄渲械淖饔脤儆谶B接的線 原型鏈概念 每個(gè)構(gòu)造函數(shù)內(nèi)部都會(huì)有一個(gè)(constructor,prototype原型對(duì)象),而且都會(huì)有一個(gè)內(nèi)置樹形__proto__屬性用于指向創(chuàng)建它函數(shù)對(duì)象的prototype原型,當(dāng)然原型對(duì)象也會(huì)有__proto__屬性,源源不斷...
摘要:對(duì)應(yīng)的關(guān)系圖如下講解了構(gòu)造函數(shù)和原型對(duì)象之間的關(guān)系,那么實(shí)例對(duì)象和原型對(duì)象之間的關(guān)系又是怎么樣的呢下面講解。原型對(duì)象的指向的是構(gòu)造函數(shù)和本身沒有屬性,但是其原型對(duì)象有該屬性,因此也能獲取到構(gòu)造函數(shù)。 JavaScript進(jìn)階 - 1. 原型和原型鏈的概念 我們好多經(jīng)常會(huì)被問道JavaScript原型和原型鏈的概念,還有關(guān)于繼承,new操作符相關(guān)的概念。本文就專門整理了原型和原型鏈的概念...
摘要:構(gòu)造函數(shù)除了以指定模式創(chuàng)建對(duì)象之外,構(gòu)造函數(shù)也做了另一個(gè)有用的事情它自動(dòng)地為新創(chuàng)建的對(duì)象設(shè)置一個(gè)原型對(duì)象。正式來說,如果思考一下分類的概念并且我們已經(jīng)對(duì)進(jìn)行了分類,那么構(gòu)造函數(shù)和原型對(duì)象合在一起可以叫作類。 這篇文章是「深入ECMA-262-3」系列的一個(gè)概覽和摘要。每個(gè)部分都包含了對(duì)應(yīng)章節(jié)的鏈接,所以你可以閱讀它們以便對(duì)其有更深的理解。 對(duì)象 ECMAScript做為一個(gè)高度抽象的面...
摘要:在這個(gè)情況下我們可能需要使用構(gòu)造函數(shù),其以指定的模式來創(chuàng)造對(duì)象。構(gòu)造函數(shù)也有自己的,值為,也通過其屬性關(guān)聯(lián)到。從邏輯上來說,這是以棧的形式實(shí)現(xiàn)的,它叫作執(zhí)行上下文棧。 原文:http://dmitrysoshnikov.com/ecmascript/javascript-the-core/ 對(duì)象 原型鏈 構(gòu)造函數(shù) 執(zhí)行上下文棧 執(zhí)行上下文 變量對(duì)象 活動(dòng)對(duì)象 作用域鏈 閉包 Thi...
閱讀 901·2021-10-13 09:39
閱讀 3781·2021-10-12 10:12
閱讀 1860·2021-08-13 15:07
閱讀 1068·2019-08-29 15:31
閱讀 2939·2019-08-26 13:25
閱讀 1840·2019-08-23 18:38
閱讀 1952·2019-08-23 18:25
閱讀 1904·2019-08-23 17:20