成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

高能!typeof Function.prototype 引發(fā)的先有 Function 還是先有 O

娣辯孩 / 979人閱讀

摘要:有個(gè)例外他就是??醋髠?cè)對象的原型鏈上是否有第一步得到。將各內(nèi)置引用類型的指向。用實(shí)例化出,,以及的行為并掛載。實(shí)例化內(nèi)置對象以及至此,所有內(nèi)置類型構(gòu)建完成。最后的最后,你還對是現(xiàn)有還是現(xiàn)有有想法了嗎以上均為個(gè)人查閱及實(shí)踐總結(jié)的觀點(diǎn)。

來個(gè)摸底測試,說出以下每個(gè)表達(dá)式的結(jié)果

function F(){};
var o = {};

typeof F;
typeof o;
typeof F.prototype;
typeof o.prototype;
typeof new F;
typeof (new F).prototype;
typeof (new F).__proto__;
typeof F.__proto__;
typeof o.__proto__;
typeof Object;
typeof Function;
typeof (new Function).prototype;
typeof (new Function).__proto__;
typeof (new Object).prototype;
typeof (new Object).__proto__;
typeof Object.prototype;
typeof Object.__proto__;
typeof Function.prototype;
typeof Function.__proto__;
function F(){};
var o = {};
                
typeof F;                          //==> function
typeof o;                          //==> object
typeof F.prototype;                //==> object
typeof o.prototype;                //==> undefinded
typeof new F;                      //==> object
typeof (new F).prototype;          //==> undefined
typeof (new F).__proto__;          //==> object
typeof F.__proto__;                //==> function
typeof o.__proto__;                //==> object
typeof Object;                     //==> function
typeof Function;                   //==> function
typeof (new Function).prototype;   //==> object
typeof (new Function).__proto__;   //==> function
typeof (new Object).prototype;     //==> undefined
typeof (new Object).__proto__;     //==> object
typeof Object.prototype;           //==> object
typeof Object.__proto__;           //==> function
typeof Function.prototype;         //==> function
typeof Function.__proto__;         //==> function

看到這里相信有不少入門不久的同學(xué)已經(jīng)產(chǎn)生疑惑了 是真的嗎 然后在瀏覽器試過一番發(fā)現(xiàn)真是如此。

解開疑惑之前先回顧些大家都知道的知識點(diǎn):

引用 MDN 關(guān)于 對象實(shí)例和對象原型對象 的闡述:

JavaScript語言的所有對象都是由Object衍生的對象;
所有對象都繼承了Object.prototype的方法和屬性,盡管它們可能被覆蓋。
例如,其它的構(gòu)造器原型覆蓋了constructor屬性并提供了其自己的toString方法。
原型對象的更改會傳播給所有的對象,除非這些屬性和方法在原型鏈中被再次覆蓋。

就如我們經(jīng)常在各類教科中看到的 所有的實(shí)例對象都是 Object 類型的實(shí)例

那么我們平時(shí)都是如何確定一個(gè)對象是否是另一個(gè)類型或?qū)ο蟮膶?shí)例的呢?

對我們可以使用 typeof 關(guān)鍵字 亦或可以使用關(guān)鍵字 instanceof 來確定某個(gè)對象是否是指定類型或?qū)ο蟮膶?shí)例:

typeof {} //object
({}) instanceof Object //true

typeof Date                      //function
Date instanceof Function         //true
typeof Date.prototype            //obejct
Date.prototype instanceof Object //true

然而針對 Object 的 prototype 屬性:

typeof Object.prototype //object

Object.prototype instanceof Object // false

為什么,要想搞清楚為什么就得明白 instanceof 這個(gè)關(guān)鍵字在表達(dá)式中發(fā)生了什么?

在弄清楚 instanceof 之前 還得弄清楚一樣?xùn)|西 就是 new 一個(gè)對象到底做了什么:

如 var a = new A(); 認(rèn)為 “a為A函數(shù)的實(shí)例對象”

new操作的過程是什么? 可以總結(jié)如下:

1.new 創(chuàng)建一個(gè)空對象{}
2.然后將A.prototype的引用放置到該對象的原型鏈上。即a.__proto__指向 A.prototype
3.執(zhí)行A函數(shù),將A中this指向該對象,執(zhí)行結(jié)束,如果沒有return那么默認(rèn)返回this引用

那么new的其中一個(gè)的作用便是把A.prototype的指向添加到了a的原型鏈中。

至此我們便知道了如下關(guān)系:

a.__proto__ === A.prototype //true

a instanceof A //true

故為何不得出一個(gè)結(jié)論:

instanceof 操作符其實(shí)就是檢查左側(cè)的元素的 __proto__鏈上有沒有右側(cè)類或?qū)ο蟮膒rototype存在。
同理 當(dāng)某某某是某某某的實(shí)例時(shí) 其實(shí)也是證明左側(cè)的__proto__鏈上有右側(cè)類或?qū)ο蟮膒rototype存在。

細(xì)節(jié)剖析如下:

1.看右側(cè)的 A 獲取其 prototype 得到 A.prototype。
2.看左側(cè) a 對象的原型鏈上是否有第一步得到 A.prototype。
1)獲取 a.__proto__對象看是否為A.prototype,是則返回 true
2)獲取 a.__proto__.__proto__ 對象看是否為A.prototype,是則返回 true
3)重復(fù)獲取左側(cè)的原型鏈上的[[Prototype]]特性即__proto__屬性進(jìn)行判斷直到為空返回 false。

校驗(yàn)真理,我們都知道 js 有幾大內(nèi)置類型 這些類型都是 Function 的實(shí)例,是 Function 類型:

out(typeof Date)     //Function
out(typeof RegExp)   //Function
out(typeof Number)   //Function
out(typeof Boolean)  //Function
out(typeof String)   //Function
out(typeof Array)    //Function
out(typeof Error)    //Function
//...

out(Date.__proto__  === Function.prototype)    //true
out(RegExp.__proto__ === Function.prototype)   //true
out(Number.__proto__ === Function.prototype)   //true
out(Boolean.__proto__ === Function.prototype)  //true
out(String.__proto__ === Function.prototype)   //true
out(Array.__proto__ === Function.prototype)    //true
out(Error.__proto__ === Function.prototype)    //true
//...

out(Object.getPrototypeOf(Date)  === Function.prototype)    //true
out(Object.getPrototypeOf(RegExp) === Function.prototype)   //true
out(Object.getPrototypeOf(Number) === Function.prototype)   //true
out(Object.getPrototypeOf(Boolean) === Function.prototype)  //true
out(Object.getPrototypeOf(String) === Function.prototype)   //true
out(Object.getPrototypeOf(Array) === Function.prototype)    //true
out(Object.getPrototypeOf(Error) === Function.prototype)    //true
//...

out( Date instanceof Function)    //true
out( RegExp instanceof Function)  //true
out( Number instanceof Function)  //true
out( Boolean instanceof Function) //true
out( String instanceof Function)  //true
out( Array instanceof Function)   //true
out( Error instanceof Function)   //true
//...

回到上述針對 Object 的 prototype 屬性疑惑 為什么到了 Object 就得不出一樣的結(jié)果了呢?

我們都知道每個(gè)函數(shù)對象亦或函數(shù)類型都會有個(gè) prototype 屬性,在其上掛載的方法和屬性均能夠被該類型實(shí)例化出來的對象共享,因?yàn)閷?shí)例化出來的對象擁有 [[Prototype]]特性即 __proto__ 屬性,js 便是通過該特性實(shí)現(xiàn)原型鏈機(jī)制。

那么這些函數(shù)的 prototype 屬性對象是否也有自己的[[Prototype]]特性即 __proto__ 屬性呢?

out(typeof Date.prototype)    //object
out(typeof RegExp.prototype)  //object
out(typeof Number.prototype)  //object
out(typeof Boolean.prototype) //object
out(typeof String.prototype)  //object
out(typeof Array.prototype)   //object
out(typeof Error.prototype)   //object

out(typeof Object.getPrototypeOf(Date.prototype))        //object
out(typeof Object.getPrototypeOf(RegExp.prototype))      //object
out(typeof Object.getPrototypeOf(Number.prototype))      //object
out(typeof Object.getPrototypeOf(Boolean.prototype))     //object
out(typeof Object.getPrototypeOf(String.prototype))      //object
out(typeof Object.getPrototypeOf(Array.prototype))       //object
out(typeof Object.getPrototypeOf(Error.prototype))       //object

out(Object.getPrototypeOf(Date.prototype) === Object.prototype)    //true
out(Object.getPrototypeOf(RegExp.prototype) === Object.prototype)  //true
out(Object.getPrototypeOf(Number.prototype) === Object.prototype)  //true
out(Object.getPrototypeOf(Boolean.prototype) === Object.prototype) //true
out(Object.getPrototypeOf(String.prototype) === Object.prototype)  //true
out(Object.getPrototypeOf(Array.prototype) === Object.prototype)   //true
out(Object.getPrototypeOf(Error.prototype) === Object.prototype)   //true

可以看出每個(gè)函數(shù)對象的 prototype 屬性也有自己的[[Prototype]]特性 而且指向的是 Object.prototype

那么是否所有對象都會有直接的[[Prototype]]特性 呢?

out( Object.getPrototypeOf( Object.getPrototypeOf(Date.prototype)))     //null
out( Object.getPrototypeOf( Object.getPrototypeOf(RegExp.prototype)))   //null
out( Object.getPrototypeOf( Object.getPrototypeOf(Number.prototype)))   //null
out( Object.getPrototypeOf( Object.getPrototypeOf(Boolean.prototype)))  //null
out( Object.getPrototypeOf( Object.getPrototypeOf(String.prototype)))   //null
out( Object.getPrototypeOf( Object.getPrototypeOf(Array.prototype)))    //null
out( Object.getPrototypeOf( Object.getPrototypeOf(Error.prototype)))    //null
out( Object.getPrototypeOf( Object.prototype))                          //null

答案是否。

有個(gè)例外他就是 Object.prototype。

回看前面的 Demo:

Object.prototype instanceof Object // false

從前面的代碼輸出我們看到 Object.prototype 對象是沒有[[Prototype]]特性的,同時(shí)前面我們也討論過 instanceof 這個(gè)關(guān)鍵字所涉及的具體操作。

我們可以具體剖析如下:

1.看右側(cè)的 Object 獲取其 prototype 得到 Object.prototype。
2.看左側(cè) Object.prototype 對象的原型鏈上是否有第一步得到 Object.prototype。
1)獲取 Object.prototype.__proto__對象為空直接返回 false。

那么為什么所有的對象都有[[Prototype]] 特性,唯獨(dú)Object.prototype沒有呢。答案很簡單:既然 JS的繼承機(jī)制是基于原型鏈的那總該有個(gè)頭吧,這個(gè)頭便是Object.prototype

再來一發(fā):

out( typeof Function)                                          //function
out( typeof Object)                                            //function
out( Object instanceof Function)                               //true
out( Function instanceof Function)                             //true

在學(xué)習(xí) JS 的過程中我們已經(jīng)知道所有的數(shù)據(jù)類型都是 Function 類型的實(shí)例,包括 Object 在內(nèi),但是我們都知道所有的對象都是 Object 的實(shí)例,這時(shí)便引出文章的題目

到底是先有 Function 還是先有 Object?
out( Function.__proto__  === Function.prototype)               //true
out( Object.__proto__  === Function.prototype)                 //true
out( Object.getPrototypeOf(Function) === Function.prototype)   //true
out( Object.getPrototypeOf(Object) === Function.prototype)     //true
out( Object.getPrototypeOf(Function) === Function.prototype)   //true
out( Object.getPrototypeOf(Object) === Function.prototype)     //true
out( Object instanceof Function)                               //true 
out( Function instanceof Function)                             //true

從上述代碼加上前面得出的結(jié)論我們可以看出

Function 和 Object 的原型鏈上都有 Function.prototype

我們再來詳細(xì)看看 Function.prototype

out( typeof Function.prototype);                // function
out( Function.prototype instanceof Object)      //true

這時(shí)候問題升華為

Function.prototype 和 Object.prototype 的關(guān)系。
out( Function.prototype.__proto__ === Object.prototype)

這時(shí)候關(guān)系已經(jīng)很明了了:

我們都知道除了 Object.prototype 之外所有對象都會有[[Prototype]]特性 即 __proto__ 屬性,故 Function.prototype 也不例外,
Function.prototype 指向的是 Object.prototype

這時(shí)候就可以清楚的知道為什么說所有類型都是 Function 的實(shí)例,同時(shí)也是 Object 的實(shí)例:

因?yàn)樗械念愋偷?b>[[Prototype]]特性 即 __proto__ 屬性均指向的是 Function.prototype ,同時(shí) Function.prototype 的[[Prototype]]特性 即 __proto__ 屬性又指向了 Object.prototype 。

故大王是Object.prototype,二王是Function.prototype,其他均是小弟,但是小弟也有等級劃分

先接著來看 Function:

out( typeof Function.prototype);                // function
out( typeof Function.__proto__);                // function
out( Function.prototype === Function.__proto__);// true

首先我們可以看出 Function.prototype 和其他類型的 prototype 屬性是 object 類型不一樣, 是 function 類型
其次 Function.__proto__ 指向了 Function.prototype。

我們知道當(dāng)一個(gè)類型實(shí)例化出對象時(shí),這些對象的便會共享掛載在該類型的 prototype 屬性上的 資源,因?yàn)檫@些對象均有[[Prototype]]特性,指向的就是實(shí)例化出這些對象的類型的 prototype

從前面的例子可以看到所有的類型的[[Prototype]]特性均指向了 Function.prototype,所以這些類型都具有了使用掛載在Function.prototype上的資源的權(quán)利。因此可以看出,當(dāng)一個(gè)對象具有使用掛載在Function.prototype上的資源的權(quán)利時(shí),及該對象[[Prototype]]指向 Function.prototype 時(shí)代表這個(gè)對象是個(gè) Function 實(shí)例是一個(gè)類型,能夠?qū)嵗鲈擃愋偷膶ο?,?dāng)然包括 Function 在內(nèi)。

又因?yàn)樗蓄愋偷?b>[[Prototype]]指向 Function.prototype 而 Function.prototype 的[[Prototype]]指向是 Object.prototype,所以這些類型都具有使用掛載在 Object.prototype 上的資源的權(quán)利。

那用這些類型實(shí)例化出來的對象呢 類型的原型鏈并不在實(shí)例化出來的對象上呀,但是這些實(shí)例化出來的對象的[[Protitype]]指向的是其類型的 prototype 屬性

往回看前面的例子 可以看到有一段

out(Object.getPrototypeOf(Date.prototype) === Object.prototype)    //true
out(Object.getPrototypeOf(RegExp.prototype) === Object.prototype)  //true
out(Object.getPrototypeOf(Number.prototype) === Object.prototype)  //true
out(Object.getPrototypeOf(Boolean.prototype) === Object.prototype) //true
out(Object.getPrototypeOf(String.prototype) === Object.prototype)  //true
out(Object.getPrototypeOf(Array.prototype) === Object.prototype)   //true
out(Object.getPrototypeOf(Error.prototype) === Object.prototype)   //true
out(Object.getPrototypeOf(Function.prototype) === Object.prototype)   //true

可以看到這些類型的 prototype 屬性的[[Protitype]]指向的是 Object.prototype 故至此,所有對象包括類型對象亦或類型實(shí)例化出來的對象都有使用掛載在 Object.prototype 上的資源的權(quán)利。

到這里所有對象之間的關(guān)系就已經(jīng)清除了,相信已經(jīng)有不少人已經(jīng)暈乎了,沒關(guān)系 我準(zhǔn)備了圖(看不太清晰是因?yàn)樯蟼骱蟊粔嚎s了):

當(dāng)然這里我還是省略了部分細(xì)節(jié) 譬如對應(yīng)類型的 prototype 屬性對象均有 constructor 屬性指向該類型,以及省略部分類型。

對著這張圖重新看一遍本文和文章開頭的摸底,相信你會有收獲。

那么為什么使用 typeof 獲取 Object.prototype 會返回 object 呢。

我們知道瀏覽器底層對 JS 的實(shí)現(xiàn)的是基于 C/C++
通過上圖,我們可以猜測

瀏覽器在初始化JS 環(huán)境時(shí)都發(fā)生了些什么

1.用 C/C++ 構(gòu)造內(nèi)部數(shù)據(jù)結(jié)構(gòu)創(chuàng)建一個(gè) OP 即(Object.prototype)以及初始化其內(nèi)部屬性但不包括行為。
2.用 C/C++ 構(gòu)造內(nèi)部數(shù)據(jù)結(jié)構(gòu)創(chuàng)建一個(gè) FP 即(Function.prototype)以及初始化其內(nèi)部屬性但不包括行為。
3.將 FP 的[[Prototype]]指向 OP。
4.用 C/C++ 構(gòu)造內(nèi)部數(shù)據(jù)結(jié)構(gòu)創(chuàng)建各種內(nèi)置引用類型。
5.將各內(nèi)置引用類型的[[Prototype]]指向 FP。
6.將 Function 的 prototype 指向 FP。
7.將 Object 的 prototype 指向 OP。
8.用 Function 實(shí)例化出 OP,F(xiàn)P,以及 Object 的行為并掛載。
9.用 Object 實(shí)例化出除 Object 以及 Function 的其他內(nèi)置引用類型的 prototype 屬性對象。
10.用 Function 實(shí)例化出除Object 以及 Function 的其他內(nèi)置引用類型的 prototype 屬性對象的行為并掛載。
11.實(shí)例化內(nèi)置對象 Math 以及 Grobal
至此,所有 內(nèi)置類型構(gòu)建完成。

現(xiàn)在我們可以回答為什么使用 typeof 獲取 Object.prototype 會返回 object 了。
因?yàn)槲覀冊谑褂?typeof 的時(shí)候得到的 object 類型并不完全代表是 Object 類型實(shí)例化出來的對象,有可能是底層實(shí)現(xiàn)的內(nèi)部數(shù)據(jù)結(jié)構(gòu),包括 null。真正想知道這個(gè)類型還是需要去到當(dāng)前該類的內(nèi)部[[Class]]屬性,至于如何獲取可以使用Object的toString方法。

最后的最后,你還對是現(xiàn)有 Function 還是現(xiàn)有 Object 有想法了嗎?

以上均為個(gè)人查閱及實(shí)踐總結(jié)的觀點(diǎn)。

謝謝~

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/79706.html

相關(guān)文章

  • 如何優(yōu)雅的理解ECMAScript中的對象

    摘要:標(biāo)準(zhǔn)對象,語義由本規(guī)范定義的對象。這意味著雖然有,本質(zhì)上依然是構(gòu)造函數(shù),并不能像那樣表演多繼承嵌套類等高難度動作。不過這里的并不是我們所說的數(shù)據(jù)類型,而是對象構(gòu)造函數(shù)。 序 ECMAScript is an object-oriented programming language for performing computations and manipulating computat...

    why_rookie 評論0 收藏0
  • JavaScript 原型中的哲學(xué)思想

    摘要:而作為構(gòu)造函數(shù),需要有個(gè)屬性用來作為以該構(gòu)造函數(shù)創(chuàng)造的實(shí)例的繼承。 歡迎來我的博客閱讀:「JavaScript 原型中的哲學(xué)思想」 記得當(dāng)年初試前端的時(shí)候,學(xué)習(xí)JavaScript過程中,原型問題一直讓我疑惑許久,那時(shí)候捧著那本著名的紅皮書,看到有關(guān)原型的講解時(shí),總是心存疑慮。 當(dāng)在JavaScript世界中走過不少旅程之后,再次萌發(fā)起研究這部分知識的欲望,翻閱了不少書籍和資料,才搞懂...

    sugarmo 評論0 收藏0
  • JavaScript原型鏈以及Object,Function之間的關(guān)系

    摘要:由于一般所有的原型鏈最終都會指向頂端的,所以它們都是的。好了現(xiàn)在了,成了所有對象原型鏈的。 JavaScript里任何東西都是對象,任何一個(gè)對象內(nèi)部都有另一個(gè)對象叫__proto__,即原型,它可以包含任何東西讓對象繼承。當(dāng)然__proto__本身也是一個(gè)對象,它自己也有自己的__proto__,這樣一級一級向上,就構(gòu)成了一個(gè)__proto__鏈,即原型鏈。當(dāng)然原型鏈不會無限向上,它有...

    zacklee 評論0 收藏0
  • 原型鏈?zhǔn)鞘裁??關(guān)于原型鏈中constructor、prototype及__proto__之間關(guān)系的認(rèn)

    摘要:的隱式原型是母,母是由構(gòu)造函數(shù)構(gòu)造的,但函數(shù)的隱式原型又是。。。??赡苁强紤]到它也是由構(gòu)造函數(shù)生成的吧,所以返回的值也是。 showImg(https://segmentfault.com/img/bVyLk0); 首先,我們暫且把object類型和function類型分開來,因?yàn)?function是一個(gè)特殊的對象類型,我們這里這是便于區(qū)分,把function類型單獨(dú)拿出來。順便一提,...

    kaka 評論0 收藏0
  • 講清楚之 javascript原形

    摘要:構(gòu)造函數(shù)和實(shí)例都通過屬性指向了原形。代碼示例是構(gòu)造函數(shù)的實(shí)例的屬性與的屬性保存的值相等,即他們指向同一個(gè)對象原形。 講清楚之javascript原型 標(biāo)簽: javascript javascript 中原形是一個(gè)比較難于理解的概念。javascript 權(quán)威指南在原形這一章也花了大量的篇幅進(jìn)行介紹,也許你已經(jīng)讀過javascript 權(quán)威指南,或者已經(jīng)是讀第N篇了,然而這篇文章的目...

    高勝山 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<