作者:doris
鏈接:https://www.zhihu.com/question/34183746/answer/58155878
來源:知乎
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)枯冈,非商業(yè)轉(zhuǎn)載請注明出處。
首先办悟,要明確幾個點:
1.在JS里尘奏,萬物皆對象。方法(Function)是對象病蛉,方法的原型(Function.prototype)是對象炫加。因此,它們都會具有對象共有的特點铺然。即:對象具有屬性_ proto_ _俗孝,可稱為隱式原型,一個對象的隱式原型指向構(gòu)造該對象的構(gòu)造函數(shù)的原型魄健,這也保證了實例能夠訪問在構(gòu)造函數(shù)原型中定義的屬性和方法赋铝。
2.方法(Function)方法這個特殊的對象,除了和其他對象一樣有上述 _ proto _屬性之外沽瘦,還有自己特有的屬性——原型屬性(prototype)革骨,這個屬性是一個指針,指向一個對象其垄,這個對象的用途就是包含所有實例共享的屬性和方法(我們把這個對象叫做原型對象)苛蒲。原型對象也有一個屬性,叫做constructor绿满,這個屬性包含了一個指針臂外,指回原構(gòu)造函數(shù)。
好啦,知道了這兩個基本點漏健,我們來看看上面這副圖嚎货。
- 1.構(gòu)造函數(shù)Foo()構(gòu)造函數(shù)的原型屬性Foo.prototype指向了原型對象,在原型對象里有共有的方法蔫浆,所有構(gòu)造函數(shù)聲明的實例(這里是f1殖属,f2)都可以共享這個方法。
- 2.原型對象Foo.prototypeFoo.prototype保存著實例共享的方法瓦盛,有一個指針constructor指回構(gòu)造函數(shù)洗显。
- 3.實例f1和f2是Foo這個對象的兩個實例,這兩個對象也有屬性 _ proto _原环,指向構(gòu)造函數(shù)的原型對象挠唆,這樣子就可以像上面1所說的訪問原型對象的所有方法啦。
另外:構(gòu)造函數(shù)Foo()除了是方法嘱吗,也是對象啊玄组,它也有 _ proto _ 屬性,指向誰呢谒麦?指向它的構(gòu)造函數(shù)的原型對象唄俄讹。函數(shù)的構(gòu)造函數(shù)不就是Function嘛,因此這里的 _ proto _ 指向了Function.prototype绕德。其實除了Foo()患膛,F(xiàn)unction(), Object()也是一樣的道理。
原型對象也是對象啊迁匠,它的 _ proto _ 屬性剩瓶,又指向誰呢?同理城丧,指向它的構(gòu)造函數(shù)的原型對象唄延曙。這里是Object.prototype.最后,Object.prototype的 _ proto _ 屬性指向null亡哄。
總結(jié):
1.對象有屬性 _ proto _ ,指向該對象的構(gòu)造函數(shù)的原型對象枝缔。
2.方法除了有屬性 _ proto _ ,還有屬性prototype,prototype指向該方法的原型對象蚊惯。
3愿卸、函數(shù)(包括構(gòu)造函數(shù))如果沒有自定義的構(gòu)造函數(shù),那么他的構(gòu)造函數(shù)就是Function截型,所以他的 _ proto _ 指向Function.prototype
4趴荸、原型對象也是對象啊,對象的構(gòu)造函數(shù)是Object宦焦,所以一般XX.prototype. _ proto _ 一定是Object.prototype
面試題理解:
var F = function(){};
Object.prototype.a = function(){};
Function.prototype.b = function(){};
var f = new F();
問:調(diào)用f.a( )和f.b( ) 能成功么发钝?
答:能調(diào)用f.a( )但是不能調(diào)用f.b( )
為什么內(nèi)顿涣?
首先一步步分析
1、
var F = function(){};
F是一個匿名函數(shù)酝豪,也是對象涛碑,函數(shù)都有prototype屬性,指向函數(shù)的原型,對象都有__ proto __屬性孵淘,指向創(chuàng)建這個對象的構(gòu)造函數(shù)的原型蒲障。F.prototype也是對象啊,創(chuàng)建這個對象的構(gòu)造函數(shù)是Object
F. __proto__ =Function.prototype
F.prototype.__proto__ =Object.prototype
2瘫证、給Object方法定義一個原型屬性a
Object.prototype.a=function(){}
3揉阎、給Function定義一個原型屬性b
Function.prototype.b = function(){};
4、用F當(dāng)做構(gòu)造函數(shù)去構(gòu)造一個對象f
f.__proto__=F.prototype;
F.prototype. __proto__=Object.prototype;
具體參照下圖
instanceof
instanceof 操作符的內(nèi)部實現(xiàn)機制和隱式原型背捌、顯式原型有直接的關(guān)系余黎。instanceof的左值一般是一個對象,右值一般是一個構(gòu)造函數(shù)载萌,用來判斷左值是否是右值的實例。它的內(nèi)部實現(xiàn)原理是這樣的:
//設(shè) L instanceof R
//通過判斷
L.__proto__.__proto__ ..... === R.prototype 巡扇?
//最終返回true or false
也就是沿著L的proto一直尋找到原型鏈末端扭仁,直到等于R.prototype為止。知道了這個也就知道為什么以下這些奇怪的表達式為什么會得到相應(yīng)的值了
Function instanceof Object // true
Object instanceof Function // true
Function instanceof Function //true
Object instanceof Object // true
Number instanceof Number //false
這個關(guān)系對應(yīng)這上圖來看就很明顯了