摘要:也就是說對(duì)象都是函數(shù)創(chuàng)建的而屬性是為了繼承而生的,所有只需要函數(shù)有就夠了構(gòu)造函數(shù)的屬性指向的是一個(gè)對(duì)象,這個(gè)對(duì)象就是我們說的原型我們知道去的路,那也要知道回來的路吧就是回來的路。
構(gòu)造函數(shù)與實(shí)例
function Foo() {}; let instance = new Foo();
構(gòu)造函數(shù)其實(shí)就是一個(gè)函數(shù),只不過我們約定俗成:構(gòu)造函數(shù)首字母大寫
在江湖上混,有些黑話還是要遵守的
實(shí)例就是用new操作符執(zhí)行構(gòu)造函數(shù)返回的對(duì)象
prototypejs里面一切皆對(duì)象,所以函數(shù)也是一種對(duì)象
既然是對(duì)象就可以有屬性,prototype就是函數(shù)的內(nèi)置屬性,而且只有函數(shù)才有prototype屬性
為什么只有函數(shù)才有prototype屬性?
因?yàn)樗械暮瘮?shù)都可以充當(dāng)構(gòu)造函數(shù),而所有的對(duì)象都是構(gòu)造函數(shù)創(chuàng)建的。也就是說對(duì)象都是函數(shù)創(chuàng)建的
而prototype屬性是為了繼承而生的,所有只需要函數(shù)有就夠了
constructor構(gòu)造函數(shù)的prototype屬性指向的是一個(gè)對(duì)象,這個(gè)對(duì)象就是我們說的原型
我們知道去的路,那也要知道回來的路吧!
constructor就是回來的路。它指向原型所在的構(gòu)造函數(shù),和prototype的方向正好相反
有一個(gè)問題
function Foo() {}; let instance = new Foo(); console.log(instance.constructor); // function Foo() {};
為什么實(shí)例的constructor屬性也指向構(gòu)造函數(shù)?
其實(shí)實(shí)例的constructor屬性不是它自己的,是原型繼承過來的
proto__proto__是實(shí)例的屬性,因?yàn)閷?shí)例是一個(gè)對(duì)象,而所有對(duì)象都是函數(shù)創(chuàng)建的,于是所有對(duì)象都有__proto__屬性
實(shí)例的__proto__屬性指向它的構(gòu)造函數(shù)的原型
一家人有了這三個(gè)屬性,實(shí)例、構(gòu)造函數(shù)、原型就有了可以互相找到對(duì)方的路,從此這一家人互相之間再也不會(huì)失了音信
function Foo() {}; let instance = new Foo(); console.log(Foo.prototype); // 原型 console.log(Foo.prototype.constructor); // 構(gòu)造函數(shù) console.log(instance.__proto__); // 原型
實(shí)例有點(diǎn)可憐,它的聯(lián)系是單向的,如果實(shí)例不主動(dòng)呼出的話,構(gòu)造函數(shù)和原型是找不到它的
Foo的構(gòu)造函數(shù)那么構(gòu)造函數(shù)Foo的構(gòu)造函數(shù)又是誰呢?
console.log(Foo.__proto__.constructor); // function Function() { [native code] }
看到那串[native code]沒?它表示到這里止步,否則,你就知道的太多了
總之,這個(gè)function Function() { [native code] }略屌
Foo的構(gòu)造函數(shù)的原型console.log(Foo.__proto__); // function() { [native code] }
一樣,我們得到一個(gè)這樣的東西function() { [native code] }
Foo.prototype的構(gòu)造函數(shù)console.log(Foo.prototype.__proto__.constructor); // function Object() { [native code] }
也帶了一串[native code],但至少我們知道它是個(gè)函數(shù)
再往上走兩步console.log(Foo.prototype.__proto__.constructor.__proto__.constructor); // function Function() { [native code] }
這是Foo.prototype的構(gòu)造函數(shù)的構(gòu)造函數(shù),喲,見到老朋友了!
再再往上走兩步console.log(Foo.prototype.__proto__.constructor.__proto__.constructor.__proto__.constructor); // function Function() { [native code] }
誒,見鬼了!往上怎么還是這哥們?
你要是不暈,其實(shí)還可以再往上走兩步,仍然是這哥們
自己生自己,是不是有點(diǎn)色即是空,空即是色的味道?
之前說了,所有對(duì)象都是函數(shù)創(chuàng)建的,這哥們就是函數(shù)始祖,是女媧用泥捏出來的
見到始祖,啥也別說,頂禮膜拜吧
Foo.prototype的構(gòu)造函數(shù)的原型console.log(Foo.prototype.__proto__); // {...}
打印出來是一個(gè)有一堆屬性的對(duì)象
Foo的原型是由Object構(gòu)造的,所以上面打印出來的就是Object.prototype
再往上走兩步console.log(Foo.prototype.__proto__.__proto__.constructor); // Uncaught TypeError: Cannot read property "constructor" of null
詭異的事情發(fā)生了,怎么會(huì)報(bào)錯(cuò)呢?
原因在于,Foo.prototype.__proto__.__proto__指向null,也就是Object的原型的原型是null
那么,Object的原型并不是構(gòu)造函數(shù)創(chuàng)建的,因?yàn)閳?bào)錯(cuò)了嘛!難道是石頭縫里蹦出來的?
燧人之世,大跡在雷澤,華胥履之,而生伏羲。是不是感覺越來越像神話了
龍生龍,鳳生鳳天靈靈,地靈靈,來一張符咒防身
看到?jīng)]有,只要是(構(gòu)造)函數(shù),最終會(huì)走向Function,進(jìn)而循環(huán);只要是原型(對(duì)象),最終會(huì)走向Object,進(jìn)而走向null
說Function是爹,說Object是娘,你有意見嗎?
instanceofconsole.log(instance instanceof Foo); // true
instanceof的原理是:沿著instance的__proto__上溯,同時(shí)沿著Foo的prototype上溯,如果能相遇,就返回true,如果始終無法相遇,就返回false
來看一個(gè)例子
console.log(Function instanceof Object); // true console.log(Object instanceof Function); // true
再次說明了,Function可不是像Array, Number, String, Boolean一樣的小弟,它和Object有說不清道不明的關(guān)系
其實(shí)原型鏈并不長乍一聽原型鏈,好像總也望不到頭,其實(shí)走兩步就到死胡同了
沒那么可怕
繼承原型鏈?zhǔn)窃趺蠢^承的呢?
再回過頭去看看符咒
如果一個(gè)對(duì)象,它既是誰的原型,又是誰的實(shí)例,那么它就是原型鏈上的一個(gè)神經(jīng)元,原型鏈就是通過這些神經(jīng)元溝通起來的
A的原型是B的實(shí)例,好理解吧!
我們也可以手動(dòng)繼承
function Parent() { this.name = "Abby"; } Parent.prototype.getName = function() { console.log(this.name); } function Child() { } Child.prototype = new Parent(); var grandson = new Child(); console.log(grandson.getName()); // Abby
當(dāng)然繼承有很多種模式,這里不展開
github原文地址嗟乎原型鏈
github博客
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/89753.html
摘要:不理解沒關(guān)系,下面會(huì)結(jié)合圖例分析上一篇高級(jí)程序設(shè)計(jì)筆記創(chuàng)建對(duì)象下一篇高級(jí)程序設(shè)計(jì)筆記繼承參考之原型鏈的解讀三張圖搞懂的原型對(duì)象與原型鏈繼承與原型鏈 文章直接從原型圖解開始的,如果對(duì)一些概念不太清除,可以結(jié)合后面幾節(jié)查看 1. 圖解原型鏈 1.1 鐵三角關(guān)系(重點(diǎn)) function Person() {}; var p = new Person(); showImg(https://s...
摘要:之前有朋友問怎么去理解原型和原型鏈的問題。理解原型鏈的小技巧將箭頭視作泛化子類到父類關(guān)系那么圖中所有的虛線將構(gòu)成一個(gè)繼承層級(jí),而實(shí)線表示屬性引用。原型鏈?zhǔn)菍?shí)現(xiàn)繼承的重要方式,原型鏈的形成是真正是靠而非。 之前有朋友問怎么去理解原型和原型鏈的問題。這個(gè)問題,在面試中,很多同學(xué)經(jīng)常都會(huì)遇到。這里給大家講講,方便大家記憶。 JavaScript的特點(diǎn)JavaScript是一門直譯式腳本...
摘要:之前有朋友問怎么去理解原型和原型鏈的問題。理解原型鏈的小技巧將箭頭視作泛化子類到父類關(guān)系那么圖中所有的虛線將構(gòu)成一個(gè)繼承層級(jí),而實(shí)線表示屬性引用。原型鏈?zhǔn)菍?shí)現(xiàn)繼承的重要方式,原型鏈的形成是真正是靠而非。 之前有朋友問怎么去理解原型和原型鏈的問題。這個(gè)問題,在面試中,很多同學(xué)經(jīng)常都會(huì)遇到。這里給大家講講,方便大家記憶。 JavaScript的特點(diǎn)JavaScript是一門直譯式腳本...
摘要:探索是如何判斷的表達(dá)式如果函數(shù)的顯式原型對(duì)象在對(duì)象的隱式原型鏈上,返回,否則返回是通過自己產(chǎn)生的實(shí)例案例案例重要注意的顯示原型和隱式原型是一樣的。面試題測(cè)試題測(cè)試題報(bào)錯(cuò)對(duì)照下圖理解 原型與原型鏈深入理解(圖解) 原型(prototype) 函數(shù)的 prototype 屬性(圖) 每個(gè)函數(shù)都有一個(gè)prototype屬性,它默認(rèn)指向一個(gè)Object空對(duì)象(即稱為:原型對(duì)象) 原型對(duì)象中有...
摘要:原型鏈和對(duì)象的原型是對(duì)象實(shí)例和它的構(gòu)造函數(shù)之間建立的鏈接,它的值是構(gòu)造函數(shù)的。對(duì)象的原型根據(jù)上文提到的構(gòu)造調(diào)用函數(shù)的時(shí)候會(huì)創(chuàng)建一個(gè)新對(duì)象,自動(dòng)將的原型指向構(gòu)造函數(shù)的對(duì)象。 showImg(https://segmentfault.com/img/remote/1460000020185197); JS的原型、原型鏈一直是比較難理解的內(nèi)容,不少初學(xué)者甚至有一定經(jīng)驗(yàn)的老鳥都不一定能完全說清...
閱讀 3444·2021-11-08 13:20
閱讀 3371·2021-09-30 09:48
閱讀 2568·2021-09-29 09:41
閱讀 596·2021-09-22 15:04
閱讀 2480·2021-08-23 09:44
閱讀 3678·2020-12-03 17:26
閱讀 1013·2019-08-30 14:10
閱讀 1571·2019-08-29 18:34