摘要:先來一個構造函數構造一個人類實例化一個對象看看的名字是什么打印結果先說一個前提只要是函數,就會有一個屬性,可以理解為子代的原型遺傳基因只要是對象,就會有一個方法,可以理解為向上尋找原型的方法。
關于javascript中的原型和原型鏈
? ? ? ? 關于javascript中的原型和原型鏈,可能都會想到一個詞“prototype”,而實際里面藏的是什么東西,才是大家應該要掌握的。
? ? ? ? 看過一些文章,將原型和原型鏈說得很枯燥難懂,其實抽絲剝繭之后,理順思路,其實原型和原型鏈沒有想象中的那么難以理解。我一直崇尚的是類比生活去理解,所以個人還是不太喜歡純敘述性的解釋。
? ? ? ? 其實很多講解的人,都是從自身角度出發的,解釋的都是理所當然的,他們無法感受我們這些菜鳥的角度,不知道我們很多個為什么。當然,當我們了解理解之后,再重新看他們的文章,說的也是頭頭是道的。
? ? ? ? 關于原型這個詞,其實很好理解,可以說成是“原來的模型”。比如說,“兒子長得就像是爸爸一個模子出來一樣”,那爸爸就是兒子的原型,兒子繼承了爸爸的一些特征,當然,兒子也會有自己的特征,這些特征,就是屬性。而有時候兒子有些特征沒有,可以在兒子的爸爸那里找到,甚至兒子爸爸那里找不到的特征,可以在爸爸的爸爸那里找到,而彼此之間維系著的,就是血緣關系,DNA傳遞,而這個關系鏈,就是我們說的原型鏈,當然,往上找祖先,找到最后肯定是炎帝黃帝了,他們就是人類始祖了,如果他們身上還找不到,再往上找,就是空了,因為往上就沒有祖先了,本來無一物,何處惹塵埃。
? ? ? ? 好了,開始來代碼了。
? ? ? ? 先來一個構造函數:
//構造一個人類 function Mankind(name){ this.name = name; } //實例化一個Dad對象 var Dad = new Mankind("BaBa"); //看看Dad的名字是什么 console.log(Dad.name); //打印結果 BaBa
? ? ? ? 先說一個前提:
? ? ? ? 只要是函數,就會有一個 prototype 屬性,可以理解為子代的原型(遺傳基因);只要是對象,就會有一個__proto__方法,可以理解為向上尋找原型的方法。
? ? ? ? 所以上面的構造函數中,Mankind這個構造函數,就會有一個prototype屬性(不是函數沒有),可以這樣訪問:Mankind.prototype,當然也可以給傳統基因添加其他特征:
//還是上面的構造函數 function Mankind(name){ this.name = name; } //還是實例化一個Dad對象 var Dad = new Mankind("BaBa"); //然后給構造函數添加特征 Mankind.prototype.sayHello = "HaHaHa"; //看看Dad有沒有sayHello特征 console.log(Dad.sayHello); //打印結果 HaHaHa
? ? ? ? 從結果可以看出,Dad本來沒有的sayHello特征,你給Dad的祖先添加了,Dad也會擁有這個特征了,其實這就是從原型鏈上找到這個屬性了。
? ? ? ? Dad對象這個實例的原型,就是Mankind.prototype這個遺傳基因。
? ? ? ? 而向上找原型,就是通過__proto__這個方法,所以:
Dad.__proto__ === Mankind.prototype ?//true
? ? ? ? 當然,Mankind.prototype也是一個對象,當然也有一個__proto__方法,通過這個方法,也是可以找到他再上一級的原型,所以:
Mankind.prototype.__proto__ === Object.prototype //true
? ? ? ? 這也是對的。因為函數的祖先是Object,所以就是指向Object.prototype這個原型?。
當然,再往上找,就是空了。
Object.prototype.__proto__ ?=== null ?//true
? ? ? ? 所以各個原型組織起來,就是一條原型鏈了:
? ? ? ? Dad ---> Mankind.prototype ---> Object.prototype ---> null ? 可以看到從對象開始的原型鏈的規律
? ? ? ? 回過頭來,其實Mankind.prototype這個對象除了__proto__這個方法外,還有一個constructor的方法,因為Mankind是函數,所以有這個方法,所以通過這個方法,可以訪問到自身這個函數:
//打印一下Mankind.prototype.constructor console.log(Mankind.prototype.constructor); //打印結果 function Mankind(name){ this.name = name; }
? ? ? ? 說到這里,相信已經類比得很清楚了。然后又會有一個疑問:
? ? ? ? 既然說函數是對象(函數對象Function,普通對象Object,Function是繼承于Object的),那么前面的構造函數Mankind可以有prototype屬性,也應該有__proto__這個方法?
? ? ? ? 沒錯,所以我們也可以有Mankind.__proto__這個方法訪問原型:
Mankind.__proto__ === Function.prototype ?//true
? ? ? ? 當然,Function.prototype 也是可以通過__proto__方法訪問原型:
Function.prototype.__proto__ === Object.prototype //true
? ? ? ? 所以也有這樣的原型鏈:
? ? ? ? Mankind ---> Function.prototype ---> Object.prototype ---> null ? 可以看到從函數開始的原型鏈的規律
? ? ? ? 當然了,我們既然有一個實例的對象Dad,當然也可以再延生下去,生一個Son來繼承Dad的啦:
//從Dad那里繼承,創建一個son對象,下面兩種方法都可以: var Son = new Object(Dad); var Son = Object.create(Dad); //修改一下兒子的name Son.name = "ErZi"; //打印一下兒子的name和原型鏈上父親的name console.log(Son.name); console.log(Son.__proto__.name);//通過__proto__方法找到父親Dad //打印結果 ErZi BaBa
? ? ? ? 所以這條原型鏈是這樣的:
? ? ? ? Son ---> Dad ---> Mankind.prototype ---> Object.prototype ---> null ? 對照從對象開始的原型鏈的規律
? ? ? ? 通過上面的一大頓啰嗦,相信已經很清楚了,最后再說一下雞和雞蛋的問題:
? ? ? ? 上面既然說到有Object.prototype,而且prototype是函數才有的,所以可以訪問到Object這個構造函數,可以用Object.prototype.constructor這個方法,當然構造函數是繼承于函數對象的,所以構造函數原型又是Function.prototype,所以也有這樣的一條原型鏈:
? ? ? ? Object ---> Function.prototype ---> Object.prototype ---> null ? 對照從函數開始的原型鏈的規律(這里的Object是構造函數)
? ? ? ? 或者表示為:
? ? ? ? Object.prototype.constructor---> Function.prototype ---> Object.prototype ---> null
? ? ? ? 這就是雞和雞蛋的問題了。
? ? ? ? 最最后,放上一張網絡上解釋很清楚的原型鏈圖,再結合我上面的啰嗦,相信就很清楚容易明白了。
? ? ? ?
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/84257.html
摘要:要用作原型的對象。函數對象可以創建普通對象,這個我們上面講過了回顧一下這是一個自定義構造函數普通對象沒法創建函數對象,凡是通過創建的對象都是函數對象,其他都是普通對象通常通過創建,可以通過來判斷。 關于js的原型和原型鏈,有人覺得這是很頭疼的一塊知識點,其實不然,它很基礎,不信,往下看要了解原型和原型鏈,我們得先從對象說起 創建對象 創建對象的三種方式: 對象直接量 通過對象直接量創建...
摘要:原文鏈接關于的原型和原型鏈,看我就夠了一參考鏈接闖關記之原型及原型鏈之原型與原型鏈一篇文章帶你理解原型和原型鏈徹底理解原型鏈一的默認指向圖解和的三角關系原型和原型鏈三張圖搞懂的原型對象與原型鏈 溫故 創建對象的三種方式 通過對象直接量 通過new創建對象 通過Object.create() js中對象分為兩種 函數對象 普通對象 仔細觀察如下代碼 function Foo(na...
摘要:對于中的引用類型而言,是保存著它們所有實例方法的真正所在。高級程序設計構造函數陌上寒原型對象有一個屬性,指向該原型對象對應的構造函數為什么有屬性那是因為是的實例。 溫故 我們先回顧一下前兩天討論的內容 創建對象的三種方式 通過對象直接量 通過new創建對象 通過Object.create() js中對象分為兩種 函數對象 普通對象 原型對象prototype 每一個函數對象都...
摘要:這幾天因為對于中的作用域鏈和原型鏈有點混淆,當訪問一個不帶有修飾的變量時,我想知道它的搜索順序,因為作用域鏈的鏈結點也是一個變量對象,那么當在這個變量對象中查找變量時會不會沿著它的原型鏈查找呢這樣就有兩種可能先查找作用域鏈前端的變量對象,然 這幾天因為對于JavaScript中的作用域鏈和原型鏈有點混淆,當訪問一個不帶有this修飾的變量時,我想知道它的搜索順序,因為作用域鏈的鏈結點也...
摘要:并沒有類繼承模型,而是使用原型對象進行原型式繼承。我們舉例說明原型鏈查找機制當訪問一個對象的屬性時,會從對象本身開始往上遍歷整個原型鏈,直到找到對應屬性為止。原始類型有以下五種型。此外,試圖查找一個不存在屬性時將會遍歷整個原型鏈。 Javascript 并沒有類繼承模型,而是使用原型對象 prototype 進行原型式繼承。 盡管人們經常將此看做是 Javascript 的一個缺點,然...
閱讀 3541·2021-11-18 13:22
閱讀 2559·2021-09-23 11:53
閱讀 726·2019-08-30 13:17
閱讀 1348·2019-08-30 13:12
閱讀 896·2019-08-29 15:43
閱讀 1102·2019-08-29 12:53
閱讀 2828·2019-08-26 18:27
閱讀 1501·2019-08-26 11:52