最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

圖解JavaScript:對象、繼承與原型鏈

2022-04-26 10:07 作者:Flinx_方凌旭  | 我要投稿

根據(jù)理論繪制示意圖

構(gòu)造函數(shù)、原型

  1. 每個function都有一個原型,functionprototype屬性指向了這個function原型

  2. 構(gòu)造函數(shù)function的一個種類,所以

  3. ●?每個構(gòu)造函數(shù)都有一個原型,構(gòu)造函數(shù)prototype屬性指向了這個構(gòu)造函數(shù)原型

  4. 每個object都是由某個構(gòu)造函數(shù)產(chǎn)生的,object__proto__屬性指向產(chǎn)生這個object構(gòu)造函數(shù)原型

注:原型是從屬于function的,應當說“function原型”,而“object原型”是“object構(gòu)造函數(shù)原型”的簡略說法。

  1. functionobject的一個種類,所以

  2. ● 每個function都是由某個構(gòu)造函數(shù)產(chǎn)生的,function__proto__屬性指向了產(chǎn)生這個function構(gòu)造函數(shù)原型

  3. 產(chǎn)生function構(gòu)造函數(shù)Function,即Functionfunction構(gòu)造函數(shù),所以

  4. ●?Function有一個原型,Functionprototype屬性指向了Function原型

    ●?每個function都是由Function產(chǎn)生的,function__proto__屬性指向了Function原型

  5. Functionfunction構(gòu)造函數(shù),所以Function是一個function,所以Function是它本身的構(gòu)造函數(shù),所以

  6. ●?Function__proto__屬性指向了Function原型

類、實例

JavaScript沒有專門的類定義。

假如有一個名為Person構(gòu)造函數(shù),由Person產(chǎn)生了一個名為person1object,我們可以認為Person是一個類的名字,person1Person類的一個實例。

圖中黃色框表示function,綠色框表示object

結(jié)合前文內(nèi)容可知,person1Person類的一個實例,表現(xiàn)為person1__proto__屬性指向Person原型。

那么從圖中可以發(fā)現(xiàn),Person__proto__屬性指向Function原型,所以說Person(一個function)是Function類的一個實例。

這是因為產(chǎn)生function構(gòu)造函數(shù)Function,所以所有的function都是Function實例。

注:prototype構(gòu)造函數(shù)的屬性,__proto__實例的屬性。然而,構(gòu)造函數(shù)本身是Function實例,所以構(gòu)造函數(shù)也有__proto__屬性。

繼承

這里直接給出結(jié)論:Teacher類繼承Person類,表現(xiàn)為Teacher原型__proto__屬性指向Person原型。

圖中綠色箭頭表示實例化自,藍色箭頭表示繼承。

觀察圖片左下角,我們還可以這樣說,Teacher類繼承Person類,表現(xiàn)為Teacher原型Person類的一個實例。這個說法在后面還會提到。

繼續(xù)給出如下信息:

  1. Function類繼承Object類,即

  2. ●?Function原型__proto__屬性指向Object原型

  3. Object構(gòu)造函數(shù),所以Object是一個function,所以FunctionObject構(gòu)造函數(shù),所以

  4. ●?Object__proto__屬性指向了Function原型

  5. 所有的都直接或間接地繼承Object類,沒有指定繼承來源的(如Person類)都默認直接繼承Object類,所以

  6. ●?Person原型__proto__屬性指向Object原型

  7. Object類是繼承的終點,Object原型__proto__屬性為null

object、function

  1. 上面所說的“名為Personfunction”,實際上是一個“名為Person的指向一個function變量

  2. 同理,“名為person1object”,實際上是一個“名為person1的指向一個object變量

  3. object本身沒有名字,而function本身有名字,保存在functionname屬性中

  4. functionlength屬性中保存函數(shù)的形參個數(shù)

  5. 所有object都會從它的構(gòu)造函數(shù)原型上繼承一個 constructor 屬性,保存對創(chuàng)建該object構(gòu)造函數(shù)的引用,換句話說,

  6. ●?構(gòu)造函數(shù)原型constructor 屬性指向該構(gòu)造函數(shù)本身

在瀏覽器中進行實驗

Object

首先嘗試在瀏覽器控制臺打印Object,它應該是一個指向Object類構(gòu)造函數(shù)內(nèi)置變量。

輸出的“?”表明這是一個function,“Object()”表明函數(shù)名為“Object”且形參列表為空。后面的大括號中本應輸出函數(shù)體,由于Object()是內(nèi)置函數(shù),故顯示為“[native code]”。

如何把Object類構(gòu)造函數(shù)作為一個object而不是function打印出來?我們可以手動創(chuàng)建一個object,令它的一個成員變量(即“屬性”)指向Object類構(gòu)造函數(shù)。

執(zhí)行{Object},它是{Object: Object}的簡寫,表示使用對象字面量語法(大括號)創(chuàng)建一個object,并把內(nèi)置變量Object(指向Object類構(gòu)造函數(shù))賦值給這個object的名為Object的屬性。圖示如下:

控制臺輸出如下:

輸出的“{Object: ?}”表明這是一個object,且它有一個名為Object的屬性,該屬性指向一個function(或者說“該屬性是一個function”)。

將其展開,可以發(fā)現(xiàn)它還有一個名為__proto__的屬性(注意縮進),且__proto__屬性指向一個Object類實例(即object)。而Object屬性指向一個函數(shù)名為“Object”且形參列表為空的function,它就是Object類構(gòu)造函數(shù)。這個Object屬性可以被展開,即達到了將一個function作為object打印出來的目的。

觀察Object類構(gòu)造函數(shù),發(fā)現(xiàn)它的確有lengthname、prototype、__proto__屬性:

  • length屬性為數(shù)值1(注意并不是理論值“0”)

  • name屬性為字符串“Object”

  • prototype屬性指向一個object,它是Object這個構(gòu)造函數(shù)原型

  • __proto__屬性指向一個function,根據(jù)前文所述,它是Function這個構(gòu)造函數(shù)原型(它并不是一個object,是例外情況),稍后進行驗證

我們手動創(chuàng)建的object必為Object類實例,所以它的__proto__屬性應當與Object類構(gòu)造函數(shù)prototype屬性指向同一個object

我們將它們各自展開,發(fā)現(xiàn)它們完全一致:

驗證如下:

接著驗證Object原型constructor 屬性指向Object本身:

注:訪問一個對象的屬性時,如果該對象內(nèi)部不存在這個屬性,那么就會去它的__proto__屬性所指向的那個對象(可以理解為父對象)里找,如果父對象也不存在這個屬性,則接著去父對象的__proto__屬性所指向的那個對象(可以理解為爺爺對象)里找,如果還沒找到,則繼續(xù)往上找……直到原型鏈頂端null。

最后,Object原型__proto__屬性為null,而不是undefined(其實 __proto__ 是個定義在 Object.prototype 上的訪問器屬性,稍后會進行說明)。

選取幾個方法作為代表,完善示意圖:

Function

執(zhí)行{Function},它是{Function: Function}的簡寫,表示使用對象字面量語法(大括號)創(chuàng)建一個object,并把內(nèi)置變量Function(指向Function類構(gòu)造函數(shù))賦值給這個object的名為Function的屬性。圖示如下:

控制臺輸出如下:

輸出的“{Function: ?}”表明這是一個object,且它有一個名為Function的屬性,該屬性指向一個function(或者說“該屬性是一個function”)。

將其展開,可以發(fā)現(xiàn)Function屬性指向一個函數(shù)名為“Function”且形參列表為空的function,它就是Function類構(gòu)造函數(shù)。

觀察Function類構(gòu)造函數(shù),發(fā)現(xiàn)它的確有length、name、prototype__proto__屬性:

  • length屬性為數(shù)值1(注意并不是理論值“0”)

  • name屬性為字符串“Function”

  • prototype屬性指向一個function,它是Function這個構(gòu)造函數(shù)原型

  • __proto__屬性指向一個function,它同樣是Function這個構(gòu)造函數(shù)原型

Function類構(gòu)造函數(shù)prototype、__proto__屬性與Object類構(gòu)造函數(shù)__proto__屬性應當指向同一個function,驗證如下:

觀察Function原型,由于它是一個function,所以有length、name、__proto__屬性,然而特殊之處是它沒有prototype屬性:

  • length屬性為數(shù)值0

  • name屬性為空字符串

  • __proto__屬性指向一個object,根據(jù)前文所述,它是Object原型,驗證如下:

Function原型雖然是一個function,但是沒有prototype屬性:

最后,驗證Function原型constructor 屬性指向Function本身:

那么Object.constructor指向誰?Function.constructor指向誰?

選取幾個方法作為代表,完善示意圖(注意Function原型改用黃色框,表示它是一個function):

使用Javascript中的原型

https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Objects/Object_prototypes#使用javascript中的原型

在控制臺執(zhí)行如下代碼,創(chuàng)建doSomething函數(shù):

我們可以添加一些屬性到doSomething原型上面:

然后,我們可以使用new運算符來在現(xiàn)在這個原型的基礎(chǔ)上,創(chuàng)建一個doSomething實例

就像上面看到的, doSomeInstancing__proto__ 屬性就是doSomething.prototype. 但是這又有什么用呢? 好吧,當你訪問 doSomeInstancing 的一個屬性, 瀏覽器首先查找 doSomeInstancing 是否有這個屬性. 如果 doSomeInstancing 沒有這個屬性, 然后瀏覽器就會在 doSomeInstancing__proto__ 中查找這個屬性(也就是 doSomething.prototype). 如果 doSomeInstancing 的 __proto__ 有這個屬性, 那么 doSomeInstancing 的 __proto__ 上的這個屬性就會被使用. 否則, 如果 doSomeInstancing 的 __proto__ 沒有這個屬性, 瀏覽器就會去查找 doSomeInstancing 的 __proto____proto__ ,看它是否有這個屬性. 默認情況下, 所有函數(shù)的原型屬性的 __proto__ 就是 window.Object.prototype. 所以 doSomeInstancing 的 __proto____proto__ (也就是 doSomething.prototype 的 __proto__ (也就是 Object.prototype)) 會被查找是否有這個屬性. 如果沒有在它里面找到這個屬性, 然后就會在 doSomeInstancing 的 __proto____proto____proto__ 里面查找. 然而這有一個問題: doSomeInstancing 的 __proto____proto____proto__ 不存在. 最后, 原型鏈上面的所有的 __proto__ 都被找完了, 瀏覽器所有已經(jīng)聲明了的 __proto__ 上都不存在這個屬性,然后就得出結(jié)論,這個屬性是 undefined.

執(zhí)行如下代碼:

輸出結(jié)果為:

new 操作符的作用

當執(zhí)行:

JavaScript 實際上執(zhí)行的是:

可以認為在使用new 操作符創(chuàng)建一個實例的過程中,存在如下的中間狀態(tài):

Object.create()

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create

Object.create()方法創(chuàng)建一個新對象,使用現(xiàn)有的對象來提供新創(chuàng)建的對象的__proto__。

注意d.__proto__undefined,而不是null。

注意控制臺把f作為Function類的一個實例打印出來。

[未完]

圖解JavaScript:對象、繼承與原型鏈的評論 (共 條)

分享到微博請遵守國家法律
德化县| 叙永县| 铜陵市| 郧西县| 上饶市| 禄劝| 富平县| 自治县| 廉江市| 东山县| 双辽市| 浠水县| 西充县| 榆林市| 安平县| 遂昌县| 齐河县| 从化市| 兴仁县| 山丹县| 永宁县| 吴桥县| 博罗县| 兰西县| 日土县| 息烽县| 商洛市| 塘沽区| 温泉县| 高台县| 周口市| 金溪县| 上饶县| 那曲县| 绥宁县| 新巴尔虎右旗| 宝鸡市| 壤塘县| 潍坊市| 石林| 宝丰县|