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

資訊專欄INFORMATION COLUMN

[學(xué)習(xí)筆記](méi) 小角度看JS原型鏈

Cciradih / 1885人閱讀

摘要:雖然在腳本中沒(méi)有標(biāo)準(zhǔn)的方式訪問(wèn),但在每個(gè)對(duì)象上都支持一個(gè)屬性,用于訪問(wèn)其構(gòu)造函數(shù)的原型對(duì)象。說(shuō)的是構(gòu)造函數(shù)和原型對(duì)象之間的關(guān)系,說(shuō)的是實(shí)例對(duì)象和原型對(duì)象之間的關(guān)系。

前言

在 segmentfault 上看到這樣一道題目:

var F = function(){};
Object.prototype.a = function(){};
Function.prototype.b = function(){};
var f = new F();

問(wèn):f 能取到a,b嗎?原理是什么?

乍一看真的有點(diǎn)懵,仔細(xì)研究了一下,發(fā)現(xiàn)還是對(duì)原型理解不透徹,所以總結(jié)一篇,填個(gè)洞~

Function和Object

在解題之前,先再說(shuō)說(shuō) 原型、原型鏈,以及 Function 和 Object 的關(guān)系,這也是本文的重點(diǎn)。

原型

在創(chuàng)建一個(gè)函數(shù)的時(shí)候,會(huì)自動(dòng)為其創(chuàng)建一個(gè)原型對(duì)象,可以通過(guò)函數(shù)的prototype屬性訪問(wèn)到。

創(chuàng)建一個(gè)構(gòu)造函數(shù)的實(shí)例對(duì)象,該實(shí)例對(duì)象內(nèi)部將包含一個(gè)指針(內(nèi)部屬性),指向構(gòu)造函數(shù)的原型對(duì)象。ECMA-262 第5版中管這個(gè)指針叫[[prototype]]。雖然在腳本中沒(méi)有標(biāo)準(zhǔn)的方式訪問(wèn)[[prototype]],但Firefox、 Safari、 Chrome在每個(gè)對(duì)象上都支持一個(gè)屬性 __proto__,用于訪問(wèn)其構(gòu)造函數(shù)的原型對(duì)象。

重要的事情再說(shuō)一遍:
構(gòu)造函數(shù)通過(guò) prototype 屬性訪問(wèn)原型對(duì)象。
實(shí)例對(duì)象通過(guò) [[prototype]] 內(nèi)部屬性訪問(wèn)原型對(duì)象,瀏覽器實(shí)現(xiàn)了 _proto_ 屬性用于實(shí)例對(duì)象訪問(wèn)原型對(duì)象。

var F = function () {};
var f = new F();
// 假設(shè)F的原型對(duì)象是 p, 則
// F.prototype === p;
// f.__proto__ === p;

再重復(fù)一遍。。prototype說(shuō)的是構(gòu)造函數(shù)和原型對(duì)象之間的關(guān)系,__proto__說(shuō)的是實(shí)例對(duì)象和原型對(duì)象之間的關(guān)系。

原型鏈

類 A繼承B,B繼承C……其實(shí)就是A的原型對(duì)象中有指針指向B的原型對(duì)象,而B(niǎo)的原型對(duì)象中有指針指向C的原型對(duì)象……注意是原型對(duì)象之間的聯(lián)系,A B C 這三個(gè)構(gòu)造函數(shù)之間并沒(méi)什么關(guān)系,所以才稱為“原型鏈”吧~

假設(shè)a是A的實(shí)例對(duì)象,則 a 的原型鏈為下圖中紫色線條所示,橙色線條連接了構(gòu)造函數(shù)和其原型對(duì)象。

由圖可以看出,原型鏈的末端是Object.prototype.__proto__null。當(dāng)查找a的某個(gè)屬性或方法時(shí),首先查找a自身有沒(méi)有,沒(méi)有則沿著原型鏈一直查找,直到找到或者最后到null返回undefined。

Function 和 Object

FunctionObject 之間的關(guān)系有點(diǎn)繞:
Object 是構(gòu)造函數(shù),既然是函數(shù),那么就是Function的實(shí)例對(duì)象;Function是構(gòu)造函數(shù),但Function.prototype是對(duì)象,既然是對(duì)象,那么就是Object的實(shí)例對(duì)象。

一切對(duì)象都是Object的實(shí)例,一切函數(shù)都是Function的實(shí)例。
ObjectFunction的實(shí)例,而Function.prototypeObject的實(shí)例。

二者的關(guān)系如下圖所示。

可見(jiàn),Object作為構(gòu)造函數(shù),它有 prototype 屬性指向 Object.prototype , 作為實(shí)例對(duì)象, 它有 Object.__proto__ 指向Function.prototype。Function是構(gòu)造函數(shù),它有prototype屬性指向Function.prototype,而Function是函數(shù),從而也是Function的實(shí)例,所以它有Function.__proto__指向Function.prototype,從而 Function.__proto__ === Function.prototypetrue。

可在Chrome控制臺(tái)下進(jìn)行驗(yàn)證,如圖。

原題解析

解決原型鏈問(wèn)題最好的辦法就是畫(huà)圖了,經(jīng)過(guò)前面的分析,這個(gè)圖畫(huà)起來(lái)應(yīng)該不成問(wèn)題,如下~

f 的原型鏈為藍(lán)色線所畫(huà),所以 f 可以訪問(wèn)到 a , 不能訪問(wèn)到 b 。

如果不畫(huà)圖,乍一看,可能會(huì)覺(jué)得f 可以訪問(wèn)到 b,那是可能跟我一樣誤認(rèn)為F.prototype指向Function.prototype,但其實(shí)F.prototype是對(duì)象而不是函數(shù),所以它的原型對(duì)象不會(huì)Function.prototype。

所以,原型鏈問(wèn)題一應(yīng)要畫(huà)圖啊~

原題擴(kuò)展

在上題中,f 只能訪問(wèn) a,不能訪問(wèn) b 。但 F 既可以訪問(wèn) a ,又可以訪問(wèn) b。
如果把題修改成下面的樣子, F.b()的結(jié)果是什么呢?為什么呢?可以想一下哦~

var F = function(){};
Object.prototype.a = function(){};
Function.prototype.b = function(){ console.log("F.__proto__") };
F.prototype.b = function (){console.log("F.prototype");};
總結(jié)

讀到這里,有沒(méi)有發(fā)現(xiàn)函數(shù)一個(gè)比較特殊的地方?
一般的對(duì)象,只有一個(gè)__proto__屬性用于訪問(wèn)其構(gòu)造函數(shù)的原型對(duì)象,而對(duì)于函數(shù)來(lái)說(shuō),它既是函數(shù)又是對(duì)象。
作為函數(shù),它生來(lái)就有prototype屬性指向其原型對(duì)象函數(shù)名.prototype
作為Function的實(shí)例對(duì)象,它有__proto__屬性指向Function.prototype
通常,這兩個(gè)屬性是指向兩個(gè)對(duì)象的,但Function的這兩個(gè)屬性指向相同,都指向Function.prototype

對(duì)于函數(shù) A( ) 來(lái)說(shuō),A.prototype 中的方法是供其實(shí)例對(duì)象調(diào)用的,自己并不會(huì)用;當(dāng)A 作為實(shí)例運(yùn)行時(shí),調(diào)用的是 A.__proto__ 中的方法。也就是說(shuō),作為構(gòu)造函數(shù)使用時(shí),走的是A.prototype這條鏈,方法、屬性賦給其實(shí)例;作為對(duì)象使用時(shí),走的是A.__proto__這條鏈。在不同的場(chǎng)景下,分清它的身份就不會(huì)錯(cuò)了。

整篇下來(lái),感覺(jué)自己說(shuō)的也比較絮叨……不足之處,還請(qǐng)各位指正~ 至于題目,真的不知道該叫什么好。。

愿本文能帶給堅(jiān)持看完的你一些收獲~ ^_^

參考

js 原型的問(wèn)題 Object 和 Function 到底是什么關(guān)系?—— 高票答案

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

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

相關(guān)文章

  • JS筆記

    摘要:從最開(kāi)始的到封裝后的都在試圖解決異步編程過(guò)程中的問(wèn)題。為了讓編程更美好,我們就需要引入來(lái)降低異步編程的復(fù)雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁(yè)面加載發(fā)生了什么這是一篇開(kāi)發(fā)的科普類文章,涉及到優(yōu)化等多個(gè)方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結(jié)思考,循序漸進(jìn)的理解 TypeScript。 網(wǎng)絡(luò)基礎(chǔ)知識(shí)之 HTTP 協(xié)議 詳細(xì)介紹 HTT...

    rottengeek 評(píng)論0 收藏0
  • [學(xué)習(xí)筆記] JavaScript 閉包

    摘要:但是,必須強(qiáng)調(diào),閉包是一個(gè)運(yùn)行期概念。通過(guò)原型鏈可以實(shí)現(xiàn)繼承,而與閉包相關(guān)的就是作用域鏈。常理來(lái)說(shuō),一個(gè)函數(shù)執(zhí)行完畢,其執(zhí)行環(huán)境的作用域鏈會(huì)被銷毀。所以此時(shí),的作用域鏈雖然銷毀了,但是其活動(dòng)對(duì)象仍在內(nèi)存中。 學(xué)習(xí)Javascript閉包(Closure)javascript的閉包JavaScript 閉包深入理解(closure)理解 Javascript 的閉包JavaScript ...

    sunsmell 評(píng)論0 收藏0
  • JS中的原型原型的認(rèn)識(shí)

    摘要:在上面的各種原型的變換中,其實(shí)難點(diǎn)就在于構(gòu)造函數(shù)也是對(duì)象原型對(duì)象等所有對(duì)象都由構(gòu)造這四個(gè)點(diǎn)。 這篇文章主要是學(xué)習(xí)一下JavaScript中的難點(diǎn)------原型和原型鏈 自定義一個(gè)對(duì)象 我們學(xué)習(xí)一門編程語(yǔ)言,必然要使用它完成一些特定的功能,而面向?qū)ο蟮恼Z(yǔ)言因?yàn)榉先祟惖恼J(rèn)知規(guī)律,在這方面做得很好,今天我以JS為例,探索一下JS不同于其他面向?qū)ο蟮恼Z(yǔ)言的地方-------原型和原型鏈 首...

    Juven 評(píng)論0 收藏0
  • JS中的原型原型的認(rèn)識(shí)

    摘要:在上面的各種原型的變換中,其實(shí)難點(diǎn)就在于構(gòu)造函數(shù)也是對(duì)象原型對(duì)象等所有對(duì)象都由構(gòu)造這四個(gè)點(diǎn)。 這篇文章主要是學(xué)習(xí)一下JavaScript中的難點(diǎn)------原型和原型鏈 自定義一個(gè)對(duì)象 我們學(xué)習(xí)一門編程語(yǔ)言,必然要使用它完成一些特定的功能,而面向?qū)ο蟮恼Z(yǔ)言因?yàn)榉先祟惖恼J(rèn)知規(guī)律,在這方面做得很好,今天我以JS為例,探索一下JS不同于其他面向?qū)ο蟮恼Z(yǔ)言的地方-------原型和原型鏈 首...

    Shimmer 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<