摘要:可以看出這個構造函數是由創建出來的,而我們看下的隱式原型,竟然是指向了的原型,也就是也是由創建出來的。例如,其他構造函數的原型將覆蓋屬性并提供自己的方法。將構造函數的執行對象賦給這個空對象并且執行。把對象的隱式原型指向構造函數的原型。
構造函數與實例對象
又是這個經典的問題,嗯,我先來寫個構造函數,然后實例化一個對象看看。
function Person(name) { this.name = name } Person.prototype.eat = () => {console.log("eat")} Person.prototype.play = () => {console.log("play")} let Han = new Person("Han")
通過一系列打印發現了這樣的關系:
可以看出實例對象沒有prototype(也就是原型),只有構造器才擁有原型。而所有的js對象都擁有__proto__(也就是隱式原型),這個隱式原型所指向的就是創造這個對象的構造器的原型。如實例Han的隱式原型指向了其構造函數(Person)的原型;Person的隱式原型指向了Function的原型;而原型自身也有隱式原型,指向了Object的原型。
有點繞口,其實就是通過隱式原型可以向上找到是誰構造了自己,并且如果自己沒有相應的屬性或者方法,可以沿著這條原型鏈向上找到最近的一個屬性或方法來調用。如Han.eat(),實際上是調用了Han.__proto__.eat(),把構造器Person的原型的eat方法給拿來用了;再如Han.hasOwnProperty("name"),實際上是調用了Han.__proto__.__proto__.hasOwnProperty("name"),因為Han自己沒hasOwnProperty這方法,就通過隱式原型向上找到了Person的原型,發現也沒這方法,就只能再沿著Person的原型的隱式原型向上找到了Object的原型,嗯然后發現有這方法就拿來調用了。
構造器constructor所有構造函數都有自己的原型(prototype),而原型一定有constructor這么個屬性,指向構造函數本身。也就是告訴大家這個原型是屬于本構造函數的。
Function & Object可以看出Person這個構造函數是由Function創建出來的,而我們看下Function的隱式原型,竟然是指向了Function的原型,也就是Function也是由Function創建出來的。很繞是不是,我們先不管,繼續溯源下去,再看下Function的原型的隱式原型,指向的是Object的原型,繼續往上找Object的原型的隱式原型,嗯終于結束了找到的是null,也就是Object的原型是原型鏈上的最后一個元素了。
接下來看下Object,Object是由Function創建出來的,而Function的隱式原型的隱式原型是Object的原型也就是Function通過原型鏈可以向上找到Object的原型,兩者看起來是你生我我生你的關系,這里也就引用比較好懂的文章來解釋下: 從Object和Function說說JS的原型鏈
Object
JavaScript中的所有對象都來自Object;所有對象從Object.prototype繼承方法和屬性,盡管它們可能被覆蓋。例如,其他構造函數的原型將覆蓋constructor屬性并提供自己的toString()方法。Object原型對象的更改將傳播到所有對象,除非受到這些更改的屬性和方法將沿原型鏈進一步覆蓋。Function
Function 構造函數 創建一個新的Function對象。 在 JavaScript 中, 每個函數實際上都是一個Function對象。---- 來自mozilla
接下來說下構造函數實例化對象到底做了些啥,其實看也能看出來了。
let Jan = {} Person.call(Jan, "Jan") Jan.__proto__ = Person.prototype
1、創建一個空對象。
2、將構造函數的執行對象this賦給這個空對象并且執行。
3、把對象的隱式原型指向構造函數的原型。
4、返回這個對象
是的就是這樣,next page!
繼承 原型鏈繼承function Person(name) { this.name = name this.skills = ["eat", "sleep"] } Person.prototype.say = ()=> {console.log("hi")} function Boss() {} Boss.prototype = new Person() let Han = new Boss()
原理就是這樣
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102575.html
摘要:組合繼承實現了屬性分離,方法共享下的完美繼承方案繼承我們的主角,,就是對組合繼承的改進。這也是為什么在子類構造函數中一定要顯示調用的原因。 談到繼承,或者更廣義上的:一個對象可以使用另外一個對象的屬性或方法。實現起來無外乎有兩種方式:apply or call 改變this的作用域原型繼承 改變__proto__指向,添加作用域鏈 而JavaScript所有的繼承實現,都是圍繞以上兩點...
摘要:這個構造函數的不管從調用方式還是內部寫法就都很有的感覺,但是從用途上來說,它其實更靠近的概念是中的工廠方法。到這里,所有關于繼承的東西講完了,接下來準備準備說說當中的封裝 所謂的對象,就是抽象化的數據本身 一個面向對象轉向面向原型的困惑 我發現Javascript這門語言每次翻開都會帶給人新感受,尤其是看完其他語言的面向對象再來看它,但是如果你也是過來人就一定記得教科書里面冗長乏味的...
摘要:深入系列第十五篇,講解各種繼承方式和優缺點。優點融合原型鏈繼承和構造函數的優點,是中最常用的繼承模式。寄生組合式繼承為了方便大家閱讀,在這里重復一下組合繼承的代碼組合繼承最大的缺點是會調用兩次父構造函數。 JavaScript深入系列第十五篇,講解JavaScript各種繼承方式和優缺點。 寫在前面 本文講解JavaScript各種繼承方式和優缺點。 但是注意: 這篇文章更像是筆記,哎...
摘要:此時的原型對象包括一個指向另一個原型的指針,相應的,另一個原型中的指向另一個構造函數。這種關系層層遞進,就通過一個原型對象鏈接另一個構造函數的原型對象的方式實現了繼承。 讀這篇之前,最好是已讀過我前面的關于對象的理解和封裝類的筆記。第6章我一共寫了3篇總結,下面是相關鏈接:讀《javaScript高級程序設計-第6章》之理解對象讀《javaScript高級程序設計-第6章》之封裝類 一...
摘要:繼承前言作為一門輕量級的腳本語言在和的橫空出世之后將其推向的新的高度雖然中出現的新的生成對象的類語法格式但依然為的語法糖而我們依然有必要從的原生實現入手來了解它的繼承實現方式給出了更加簡潔的固定的類聲明方式有興趣的可以查看阮一峰的入門下面給 javascript繼承 前言 javascript作為一門輕量級的腳本語言在ES6和node.js的橫空出世之后將其推向的新的高度,雖然 ES6...
閱讀 2907·2021-10-19 10:09
閱讀 3126·2021-10-09 09:41
閱讀 3371·2021-09-26 09:47
閱讀 2687·2019-08-30 15:56
閱讀 590·2019-08-29 17:04
閱讀 979·2019-08-26 11:58
閱讀 2505·2019-08-26 11:51
閱讀 3353·2019-08-26 11:29