原型鏈類型的題在面試中屬於高頻考點,下面用一個經典的面試題還原js中原型鏈的真面目。javascript
請問:f有方法a和方法b嗎?java
var F = function () {}; Object.prototype.a = function () {}; Function.prototype.b = function () {} ; var f = new F()
在作這題以前,必定要了解js中原型鏈的一些繼承關係,把那種繼承關係圖記在腦子裏,而後看到題目後把各自一一對應尋找繼承關係,以前走過彎路,初學js時在網上找原型鏈的圖,又複雜又記不住,相似這種:
不要看了,反正我是看不下去。面試
在js中,對象都有__proto__屬性,通常這個是被稱爲隱式原型,該隱式原型指向構造該對象的構造函數的原型。
函數比較特殊,它除了和其餘對象同樣有__proto__屬性,還有本身特有的屬性----prototype,這個屬性是一個指針,指向一個包含全部實例共享的屬性和方法的對象,稱之爲原型對象。原型對象也有一個constructor屬性,該屬性指回該函數。segmentfault
按照上述的理論能夠把構造函數(函數)、對象(構造函數new出來的)、Object(頂層的對象)之間的大概關係串起來。相似以下:函數
這張圖是我在吳華的javascript高級進階課程中看到的截圖,受用至今。
記住這四個最主要的點就ok了,對照上圖理解記憶:spa
隱式原型
(__proto__
),它指向構造函數的原型對象(prototype
)。隱式原型
(__proto__
)它指向Object
的原型對象(prototype
).Object
的原型對象有個constructor
指向Object
自己。constructor
指向構造函數自己。這裏看完你就能明白對象上的toString()
或者valueof()
是怎麼來的了,打印一下Object
的原型對象,就能獲得結果,你去訪問對象的屬性(包括方法),他會先找自身有沒有這個屬性,沒有的話會沿着原型鏈一層一層往上找,例如上圖,我要訪問obj
的showAge
方法,他自己有,返回他自己的showAge
方法,要訪問showUserName
,obj
沒有,會沿着隱式原型去看看構造函數的原型對象有沒有,有的話返回,沒有的話繼續去Object
的原型對象去找,依次往上。這也不難理解爲何對象上都有toString()
方法了。prototype
理解原型鏈後,再回到最初的那道面試題:指針
在 JavaScript 中,用 new 關鍵字來調用的函數,稱爲構造函數。構造函數首字母通常大寫
那我理解的是理論上任何一個函數均可以當成一個構造函數。
其實上面的原型圖還有一部分Function
的沒畫出來。
瞭解這個以前,帶着另外一個面試題去思考:
原型鏈頂層是什麼?按照上面的圖你可能會認爲是Object
或者Object.prototype
,其實不是。
注意:code
要理解原型鏈頂層要和原型鏈其餘地方的理解有一些不一樣,這裏Object和Function及其原型要分開看,不能將原型和自己看做是理所固然的關係