摘要:說白了,原型就是構(gòu)造函數(shù)用來構(gòu)造新實例的模板對象。什么是原型鏈先回答什么是原型。例如這個原型的原型就是這個構(gòu)造函數(shù)的,既這個原型對象。這些原型對象通過像鏈子一樣連起來,就叫做原型鏈。
原型鏈初步學(xué)習(xí)
這篇博客只是我初步理解原型鏈的一個個人學(xué)習(xí)筆記,寫的比較粗略,且有的地方可能理解錯誤.
更多更專業(yè)的關(guān)于原型鏈的解釋請看JavaScript深入之從原型到原型鏈和阮一峰的博客:Javascript繼承機制的設(shè)計思想
JS標(biāo)準(zhǔn)庫里幾個構(gòu)造函數(shù)之間的關(guān)系
每個對象都有toString()和valueOf()函數(shù),如果每個對象里都存這樣的相同的函數(shù),那會浪費內(nèi)存.
問題解決方法:原型鏈
把toString()和valueOf()等函數(shù)多帶帶存放在一個對象里,原來對象里的toString()和valueOf()只存地址,指向這個地址
當(dāng)聲明對象是,出來自己定義的屬性,還有一個隱藏的屬性
__proto__ 里面存的是toString()和valueOf()等的地址
他的值就是公用屬性的值
共有的屬性和方法
在執(zhí)行o1.toString()是發(fā)生的事:
首先看o1
是不是真正的對象,如果不是,就包裝成臨時對象,用完再回收垃圾,然后進入對象,看他有沒有toString方法,如果有特有的toString(),就用,如果沒有,就進入__proto__屬性去找toString()方法.
說明所有的toString()都是同一個地址
如果這個對象不是普通對象擁有特有的方法,會一層一層去找
代碼:
第一層的toString()是Number()特有的,可以轉(zhuǎn)換成16進制
toString(16),第二層里面的的toString()是所有對象都有的公共屬性.比如找valueOf()如果在第一層里 __proto__ 找不到,就去第二層找.
數(shù)字對象普通對象
結(jié)構(gòu):
原型鏈
所有的共有屬性,,如果沒有東西引用他,就會被垃圾回收,那么誰在引用他呢?
答案是 prototype ,prototype的意思是 原型.
所有函數(shù)都有protoype屬性,包括構(gòu)造函數(shù).即String(),Number(),Boolean(),Object()有protoype
在最開始JS初始化的時候,函數(shù)的protoype屬性會加載到內(nèi)存當(dāng)中
原型===共有屬性
Object.prototype意思還是Object的共有屬性
Object是構(gòu)造函數(shù)(JS里函數(shù)也是一種對象,也可以有方法,可以 有屬性)
函數(shù)名字加()就是執(zhí)行.
Number的共有屬性
共有屬性的共有屬性
其他String,Boolean的原型也是一樣
new做的事情,一創(chuàng)造一個哈希,二綁定原型(共有屬性),即把__proto__指向該有的共有屬性,也就是原型
__proto__與prototype的關(guān)系[__proto__指向prototype],
在無代碼情況下
window里面有Number屬性(函數(shù)也是對象,也可以有屬性)
實際上為
Number:function Number(){}這個
無代碼的時候,即為下面這樣,瀏覽器已經(jīng)將其初始化好了.
可以看到prototype是用來指向這些共有屬性的,不然這些共有屬性就被垃圾回收了,所以要用一個線來牽引著.
如圖
寫了代碼之后
所以:
prototype是瀏覽器開始就準(zhǔn)備好了的,用來防止共有屬性被垃圾回收的,
__proto__是在開始寫代碼的時候用來引用共有函數(shù)的.
String.prototype是String的公用屬性的引用,是JS在初始化的時候就已經(jīng)存在的,用他是因為如果不用他,那么公用屬性就跑了,被垃圾回收了
"s".__proto__是String的公用屬性的引用,是在聲明新對象的時候存在的,有他是因為我要用他,用公用屬性
共同點就是都是公共屬性的引用.
var o1 = {}; o1.__proto__ === Object.prototype//true
Number.prototype.__proto__===Object.prototype//true
var s1 = new String("s1"); s1.__proto__ === String.prototype//true
String.prototype.__proto__ ===Object.prototype//true function DOG(name){ this.name = name; } DOG.prototype.__proto__ === Object.prototype//true對象與構(gòu)造函數(shù)
形式
只有函數(shù)才能有prototype
兩個屬性對比:
共同點:存的地址相同,都指向同一個對象
不同點:一個是對象的屬性,一個是函數(shù)的屬性
面試題:
1
"1".__proto__
"1"會創(chuàng)建一個臨時String對象,然后指向String.prototype
2
函數(shù).prototype 是一個對象,那么
var obj = 函數(shù).prototype; obj.__proto__ === Object.prototype;//true 函數(shù).prototype.__proto__ === Object.prototype;//true
成立(可以看上圖無代碼的時候)
Number.prototype.__proto__ === Object.prototype //true String.prototype.__proto__ === Object.prototype //true Boolean.prototype.__proto__ === Object.prototype //true
成立
原型鏈面試:怎么回答
JS 原型是什么?舉例
var a = [1,2,3]
只有0、1、2、length 4 個key
為什么可以 a.push(4) ,push 是哪來的?
a.__proto__ === Array.prototype(a是實例數(shù)組對象,Array是構(gòu)造函數(shù))
push函數(shù) 就是沿著 a.__proto__ 找到的,也就是 Array.prototype.push
Array.prototype 還有很多方法,如 join、pop、slice、splice、concat
Array.prototype 就是 a 的原型(proto)
聚完例子后用new對象舉例,說給面試官聽:
比若說
我們新創(chuàng)建一個構(gòu)造函數(shù)
function Person() {}
然后根據(jù)構(gòu)造函數(shù)構(gòu)造一個新對象
var person1 = new Person();
每個函數(shù)都有一個 prototype 屬性,這個構(gòu)造函數(shù)的 prototype 屬性指向了一個對象,這個對象正是調(diào)用該構(gòu)造函數(shù)而創(chuàng)建的實例的原型。
當(dāng)我們給Person的prototype的name屬性賦值為"Kevin"
Person.prototype.name = "Kevin"; var person1 = new Person(); var person2 = new Person(); console.log(person1.name) // Kevin console.log(person2.name) // Kevin
每一個新的實例對象對象都會從原型"繼承"屬性,實例對象擁有該原型的所有屬性。
說白了,原型就是 構(gòu)造函數(shù) 用來 構(gòu)造 新實例 的 模板對象。
這就是原型。
開始解釋原型鏈
那么我們該怎么表示實例與實例原型,也就是 person1 和 Person.prototype 之間的關(guān)系呢,這時候我們就要講到第二個屬性__proto__。
先回答什么是原型。在上面,然后繼續(xù)從__proto__開始往下說。
說:
JavaScript對象除了 null 都具有的一個屬性,叫__proto__,這個屬性會指向該對象的原型對象。
當(dāng)讀取實例的屬性時,如果找不到,就會通過__proto__查找原型中的屬性,如果還查不到,就去找原型的原型。
例如Person.prototype這個原型的原型就是Object這個構(gòu)造函數(shù)的prototype,既Object.prototype這個原型對象。然后,Person.prototype.__proto__就指向Object.prototype這個原型。然后Object.prototype原型是null。
這些原型對象通過__proto__像鏈子一樣連起來,就叫做原型鏈。
然后給面試官畫:
鏈子上都畫上__proto__
person1----->Person.prototype----->Object.prototype----->null
Array.prototype----->Object.prototype----->null
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/94834.html
摘要:原文鏈接關(guān)于的原型和原型鏈,看我就夠了一參考鏈接闖關(guān)記之原型及原型鏈之原型與原型鏈一篇文章帶你理解原型和原型鏈徹底理解原型鏈一的默認(rèn)指向圖解和的三角關(guān)系原型和原型鏈三張圖搞懂的原型對象與原型鏈 溫故 創(chuàng)建對象的三種方式 通過對象直接量 通過new創(chuàng)建對象 通過Object.create() js中對象分為兩種 函數(shù)對象 普通對象 仔細(xì)觀察如下代碼 function Foo(na...
摘要:繼承可以使得子類具有父類別的各種屬性和方法。繼承是類與類之間的關(guān)系。繼承的實質(zhì)就是兩次的原型搜索,像是實例屬性而不是繼承,才是繼承。更多用法見繼承。 前言 面試中最常會問到的問題:什么是繼承?如何分別用 ES5 和 ES6 實現(xiàn)?想要學(xué)習(xí)繼承,必須先學(xué)好原型與原型鏈,如果此部分還不清楚,請先學(xué)習(xí)此部分再來閱讀本文,可參考我的文章JS之原型與原型鏈或瀏覽其他相關(guān)的學(xué)習(xí)網(wǎng)站。 定義 繼承...
摘要:對應(yīng)的關(guān)系圖如下講解了構(gòu)造函數(shù)和原型對象之間的關(guān)系,那么實例對象和原型對象之間的關(guān)系又是怎么樣的呢下面講解。原型對象的指向的是構(gòu)造函數(shù)和本身沒有屬性,但是其原型對象有該屬性,因此也能獲取到構(gòu)造函數(shù)。 JavaScript進階 - 1. 原型和原型鏈的概念 我們好多經(jīng)常會被問道JavaScript原型和原型鏈的概念,還有關(guān)于繼承,new操作符相關(guān)的概念。本文就專門整理了原型和原型鏈的概念...
摘要:的過程新生成了一個對象鏈接到原型綁定返回新對象在調(diào)用的過程中會發(fā)生以上四件事情,我們也可以試著來自己實現(xiàn)一個創(chuàng)建一個空的對象獲得構(gòu)造函數(shù)鏈接到原型綁定,執(zhí)行構(gòu)造函數(shù)確保出來的是個對象對于實例對象來說,都是通過產(chǎn)生的,無論是還是。 showImg(https://segmentfault.com/img/bVbhZun?w=488&h=590); prototype 首先來介紹下 pro...
閱讀 2528·2023-04-25 14:54
閱讀 599·2021-11-24 09:39
閱讀 1808·2021-10-26 09:51
閱讀 3853·2021-08-21 14:10
閱讀 3483·2021-08-19 11:13
閱讀 2694·2019-08-30 14:23
閱讀 1808·2019-08-29 16:28
閱讀 3356·2019-08-23 13:45