一、什么是原型
1.1 先了解幾個概念
1.構(gòu)造函數(shù)
function Dog() {
} //我就是構(gòu)造函數(shù)
var dog = new Dog();
在這里Dog就是一個構(gòu)造函數(shù),我們使用 new 創(chuàng)建了一個實例對象 dog。
2.原型對象:在聲明了一個函數(shù)之后,瀏覽器會自動按照一定的規(guī)則創(chuàng)建一個對象徙邻,這個對象就叫做原型對象。這個原型對象其實是儲存在了內(nèi)存當中畸裳。
3.在聲明了一個函數(shù)后缰犁,這個構(gòu)造函數(shù)(聲明了的函數(shù))中會有一個屬性prototype,這個屬性指向的就是這個構(gòu)造函數(shù)(聲明了的函數(shù))對應(yīng)的原型對象怖糊;原型對象中有一個屬性constructor帅容,這個屬性指向的是這個構(gòu)造函數(shù)(聲明了的函數(shù))。下面一張圖可以很簡單理解:
1.2 使用構(gòu)造函數(shù)創(chuàng)建對象
我們使用 new 創(chuàng)建了一個實例對象 stu伍伤。
function Students() {
/* 我就是構(gòu)造函數(shù) */
}
var stu = new students();
此時并徘,stu就是那個構(gòu)造函數(shù)Students創(chuàng)建出來的對象,這個stu對象中是沒有prototype屬性的扰魂,prototype屬性只有在構(gòu)造函數(shù)students中有麦乞。
可以看出蕴茴,構(gòu)造函數(shù)Students中有prototype屬性,指向的是Students對應(yīng)的原型對象姐直;而stu是構(gòu)造函數(shù)Students創(chuàng)建出來的對象倦淀,他不存在prototype屬性,所以在調(diào)用prototype的時候的結(jié)構(gòu)是undefined声畏,但stu有一個__proto__
屬性撞叽,stu調(diào)用這個屬性可以直接訪問到構(gòu)造函數(shù)Students的原型對象(也就是說,stu的 __proto__
屬性指向的是構(gòu)造函數(shù)的原型對象)插龄,如圖愿棋。
說明:
1.創(chuàng)建stu對象雖然使用的是Students構(gòu)造函數(shù),但是對象創(chuàng)建出來之后辫狼,這個stu對象其實已經(jīng)與Students構(gòu)造函數(shù)沒有任何關(guān)系了初斑。stu對象的__proto__
屬性指向的是Students構(gòu)造函數(shù)的原型對象。
2.如果使用new Students()創(chuàng)建多個對象stu1膨处、stu2、stu3砂竖,則多個對象都會同時指向students構(gòu)造函數(shù)的原型對象真椿。
3.我們可以手動給這個原型對象添加屬性和方法,那么stu1,stu2,stu3…這些對象就會共享這些在原型中添加的屬性和方法乎澄。
4.如果我們訪問stu中的一個屬性name突硝,如果在stu對象中找到,則直接返回置济。如果stu對象中沒有找到解恰,則直接去stu對象的__proto__
屬性指向的原型對象中查找,如果查找到則返回浙于。(如果原型中也沒有找到护盈,則繼續(xù)向上找原型的原型—原型鏈)。
5.如果通過stu對象添加了一個屬性name羞酗,則stu對象來說就屏蔽了原型中的屬性name腐宋。 換句話說:在stu中就沒有辦法訪問到原型的屬性name了。
6.通過stu對象只能讀取原型中的屬性name的值檀轨,而不能修改原型中的屬性name的值胸竞。 stu.name = “李四”; 并不是修改了原型中的值,而是在stu對象中給添加了一個屬性name参萄。
1.3 prototype
每個函數(shù)都有一個 prototype 屬性,他指向了這個構(gòu)造函數(shù)的原型對象卫枝。
1.4__proto__
這是每一個JavaScript對象(除了 null )都具有的一個屬性,叫__proto__
讹挎,這個屬性會指向該對象的原型校赤。
function Person() {
}
var person = new Person();
console.log(person.__proto__ === Person.prototype); // true
2 原型鏈
1.查找屬性吆玖,如果本身沒有,則會去__proto__
中查找痒谴,也就是構(gòu)造函數(shù)的顯式原型中查找衰伯,如果構(gòu)造函數(shù)中也沒有該屬性,因為構(gòu)造函數(shù)也是對象积蔚,也有proto意鲸,那么會去它的顯式原型中查找,一直到null尽爆,如果沒有則返回undefined.
2.p.__proto__.constructor == function Person(){}
3.p.___proto__.__proto__== Object.prototype
4.p.___proto__.__proto__.__proto__== Object.prototype.__proto__ == null
5.通過__proto__
形成原型鏈而非protrotype