這篇博客主要是為了理清自己的思路。
先上圖,所有內容都從這張圖來講。
在js中,所有的東西都是對象,包括是function。
prototype這個屬性是函數特有的。有兩層含義,第一層含義指的是某對象的屬性,而第二層則是作為一個對象。
比如,Foo.prototype → → → Foo.prototype,它指的就是 Foo的原型屬性 指向 Foo的原型對象。
proto我們可以把它叫做隱式原型,每個對象都具有該屬性,它指向創建該對象的那個構造函數的原型對象。
下面開始分析圖表
function Foo(){ }
Foo.prototype.a=function(){}
Foo.prototype.b=function(){}
var f1=new Foo()
在這裡我們實例化Foo函數,創建了一個f1的對象,那麼,f1這個對象擁有一個隱式的原型(_proto_),因為f1的構造函數(即創建f1這個實例)的函數式Foo,所以
f1的隱式原型就指向了Foo的原型對象,而Foo的原型對象是什麼呢?就是我們上面說的Foo.prototype。
我們可以在Foo的原型對象上綁定很多實用的方法,如上,我們在原型對象上綁定了a,b兩種方法,又由於我們的f1通過隱式原型可以訪問到Foo的原型對象,因此,我們的
實例f1就可以使用綁定在Foo上面的方法了,而這種繼承方式就是我們平時說的原型式繼承。
我們再看,按照我們最先的說法,一切皆對象,所以function Foo()這貨本身也是一個對象,既然是對象,那麼也有proto這個屬性吧,而它的隱式原型指向誰呢?
別急,我們慢慢來看,我們在創建函數的時候是不是有過這樣的寫法,
var Foo=new Function()
所以說呢,Foo的構造函數就是Function啦,那就是說我們的function Foo()這個對象它的隱式原型proto指向的就是Function.prototype了。
var o1=new Object()
按照這樣的思路我們也不難發現,o1的proto指向的就是Object.prototype。
既然說到了Object.prototype,那麼我們不得不理清一下Foo.prototype,Function.prototype和它的關系了。
Foo.prototype,Function.prototype分別是Foo的原型對象和Function的原型對象,這兩者都是對象,既然是對象的話都有proto,
proto指向的是它的構造函數的原型對象,所以就是o1這個實例一樣,它們的proto指向的就是Object.prototype。
而Object.prototype的proto就指向null了。至此整個圖的關系就都出來了。
正是因為f1的proto指向Foo.prototype,而Foo.prototype的proto指向了Object.prototype,所以我們
才能夠在f1這個實例上調用Object上綁定的原型方法,例如toString等。