函數(shù)對(duì)象
對(duì)于函數(shù)對(duì)象來(lái)說(shuō),它的proto都是指向Function.prototype。函數(shù)對(duì)象可以是如下幾種構(gòu)造器:Number,Boolean,String,Object,Function,Array,RegExp,Error,Date
//舉個(gè)栗子
Number.__proto__ === Function.prototype;
Number.constructor === Function
要記酌舸ⅰ:所有的構(gòu)造器都來(lái)自于Function.prototype,甚至包括根構(gòu)造器 Object
及Function
自身盖腕。
但是Math妨退、JSON一直都是以對(duì)象的形式存在的,不需要使用New锭魔,所以他們的__proto__
指向的是Object.prototype.
//再舉個(gè)栗子
Math.__proto__ === Object.prototype;
Math.constructor === Object
我們?cè)谥耙呀?jīng)提過(guò)例证,除了Function.prototype的類型是function,其他的構(gòu)造器的prototype都是一個(gè)對(duì)象迷捧。
typeof Function.prototype //function
typeof Object.prototype //Object
typeof Error.prototype //Object
typeof Date.prototype //Object
綜上所述:所有的構(gòu)造器的__proto__
都是Function.prototype
织咧,那么我們think一下Function.prototype的__proto__
是什么呢?經(jīng)過(guò)驗(yàn)證得出:
Function.prototype.__proto__ === Object.prototype
從側(cè)面驗(yàn)證了所有的構(gòu)造器都是一個(gè)普通的js對(duì)象漠秋,與此同時(shí)構(gòu)造器也繼承了Object.prototype上面的所有的方法:toString笙蒙,valueOf等,而之所以Object.prototype.__proto__ === null
是因?yàn)樵玩溡呀?jīng)到頂了~~~
Prototype
我們研究了這么多的原型和原型鏈的知識(shí)膛堤,但是為什么我們一定要定義prototype
屬性呢手趣,對(duì)于ECMAScript中的引用類型來(lái)說(shuō),prototype是保存著他們所有實(shí)例方法的真正的地方肥荔,也就是說(shuō)我們?cè)谑褂靡恍┖芷匠5姆椒ǎ纾簍oString()和valueOf() 朝群,這些方法都是保存在prototype上面的燕耿,只不過(guò)是在使用的時(shí)候通過(guò)各自的對(duì)象進(jìn)行實(shí)例的訪問(wèn)罷了。
當(dāng)我們聲明一個(gè)實(shí)例的時(shí)候:
var Student = new Object()
姜胖,這個(gè)時(shí)候我們發(fā)現(xiàn)Student
繼承了Object的原型對(duì)象Object.prototype
的所有的方法誉帅。這就是我們定義且使用prototype的初衷。右莱、對(duì)于Js內(nèi)置的構(gòu)造器我們已經(jīng)有了一定的認(rèn)識(shí)蚜锨,我們看一下我們自己定義的構(gòu)造器,我們先定義一個(gè)
Student
的構(gòu)造器:
function Student(name){
this.name = name;
}
var p = new Student ('kim')
//p.__proto__=== Student.prototype
粗淺的解釋一下:p
是Student
的實(shí)例對(duì)象慢蜓,p的內(nèi)部原型總是指向Student
的原型對(duì)象prototype
亚再。
function Student(name){
this.name = name;
}
var p = new Student ('kim');
///p.__proto__=== p.constructor.prototype;
因?yàn)槊恳粋€(gè)對(duì)象都有一個(gè)constructor的屬性,可以用來(lái)獲取它的構(gòu)造器晨抡,所以注釋里面的結(jié)果也是恒等于的氛悬。
現(xiàn)在我們已經(jīng)弄明白了上面是原型屬性则剃,以及構(gòu)造函數(shù)、原型如捅、__proto__
之間的關(guān)系棍现,我們考慮如果我們修改來(lái)原型,會(huì)有什么影響:
function Student(name) {
this.name = name
}
// 修改原型
Student.prototype.getName = function() {}
var p = new Student('kim')
//p.__proto__ === Student.prototype
//p.__proto__ === p.constructor.prototype
上面的情況很好被理解镜遣,但是如果現(xiàn)在的情況是我們重寫了原型己肮,那現(xiàn)在的情況還會(huì)是這樣嗎?我們看一下下面的例子:
function Student(name) {
this.name = name
}
// 修改原型
Student.prototype ={getName: function() {}}
var p = new Student('kim')
//p.__proto__ === Student.prototype
//p.__proto__!== p.constructor.prototype
這個(gè)時(shí)候悲关,我們看到了p.__proto__!== p.constructor.prototype
和上面比較發(fā)生了變化谎僻,這是為什么呢?因?yàn)?code>Student.prototype賦值的是一個(gè)直接的對(duì)象直接量坚洽,使用對(duì)象直接量方式定義的對(duì)象戈稿,他的構(gòu)造器(constructor
)指向的是根構(gòu)造器Object
,也就是說(shuō)Object.prototype
是一個(gè)對(duì)象,這個(gè)對(duì)象就是上面最開(kāi)始打出的值,這個(gè)值和{getName: function() {}}
一定是不相等的讶舰。
總結(jié)
- 原型和原型鏈?zhǔn)荍S實(shí)現(xiàn)繼承的一種模型鞍盗。
- 原型鏈的形成是是通過(guò)
__proto__
實(shí)現(xiàn)的,而不是prototype跳昼,prototype主要是進(jìn)行屬性共享的般甲。