原型對象(prototype)概念
在構(gòu)造函數(shù)創(chuàng)建出來的時(shí)候,系統(tǒng)會(huì)默認(rèn)幫構(gòu)造函數(shù)創(chuàng)建并關(guān)聯(lián)的一個(gè)新對象
自定義構(gòu)造函數(shù)的原型對象默認(rèn)是一個(gè)空對象。
原型對象(prototype)作用
構(gòu)造函數(shù)中的原型對象中的屬性和方法可以被使用該構(gòu)造函數(shù)創(chuàng)建出來的對象共享使用。
即以自定義構(gòu)造函數(shù)方式創(chuàng)建出來的所有對象,自動(dòng)擁有和共享該構(gòu)造函數(shù)的原型對象中的所有屬性和方法。
訪問原型對象的方法
- 構(gòu)造函數(shù).prototype
- 對象._proto_ (不推薦)
- Object.getPrototypeOf(對象)
設(shè)置原型對象的屬性和方法
- 利用對象的動(dòng)態(tài)特性來為構(gòu)造函數(shù)的原型對象添加屬性和方法
- 替換原型對象
原型對象的使用方法
- 利用對象的動(dòng)態(tài)特性給原型添加屬性|方法(如果要添加的方法過多,則有大量重復(fù)代碼)
- 直接替換原型對象
- 替換前后創(chuàng)建的對象所指向的原型對象不一致
- 替換原型對象會(huì)切斷和之前的原型對象之間的關(guān)系
原型對象的使用注意
- 訪問屬性:構(gòu)造函數(shù)創(chuàng)建出來的對象在訪問屬性的時(shí)候,會(huì)先在實(shí)例內(nèi)查找,如果沒有找到則進(jìn)一步到對應(yīng)的原型對象中查找
- 設(shè)置屬性:在使用點(diǎn)語法進(jìn)行賦值的時(shí)候,無法操作到對應(yīng)的原型對象
- 如果該屬性在對象中已經(jīng)存在,則修改該屬性的值
- 如果該屬性在對象中尚未存在,則新增該屬性
- 設(shè)置原型對象的屬性
- 設(shè)置原型對象的屬性,只能通過構(gòu)造函數(shù).Prototype的方式|替換原型對象的方式設(shè)置
- 如果原型對象的屬性是值類型,那么只能通過Person.prototype.屬性的方式修改其值
- 如果原型對象的屬性是引用類型,那么可以通過對象名.引用對象.屬性名的方式設(shè)置|修改
- 使用構(gòu)造函數(shù)創(chuàng)建出來的多個(gè)對象的原型對象中的該屬性指向的是同一塊數(shù)據(jù)
- 某個(gè)對象對該原型對象屬性進(jìn)行了修改會(huì)影響到其他的對象
示例代碼
function Car(color,wheel){
this.color = color;
this.wheel = wheel;
}
//instanceOf 判斷構(gòu)造函數(shù)的原型對象是否在當(dāng)前對象的原型鏈上面
var car1 = new Car('white',4);
console.log(car1 instanceof Car); //true
Car.prototype = {
constructor:Car,
run: function () {
console.log("running");
},
stop: function () {
console.log("stop");
},
owner:'洋洋'
};
console.log(car1 instanceof Car); //false
// car1.run(); //報(bào)錯(cuò)
var car2 = new Car('black',4);
var car3 = new Car('green',4);
注意:
- car1這個(gè)對象是在該構(gòu)造函數(shù)的原型對象前創(chuàng)建的,當(dāng)Car沒有通過字面量方式聲明原型對象時(shí),car1 instanceof Car為true;當(dāng)Car通過字面量方式新聲明原型對象時(shí),car1 instanceof Car為false;
A instanceof B,當(dāng)且僅當(dāng)B在A的原型鏈上時(shí),結(jié)果才為true,否則為false
instanceof注意點(diǎn).png
如上圖,也因此car1訪問不到新的原型對象,一旦訪問自身沒有而原型對象中存在的屬性或者方法,則報(bào)錯(cuò)。 - 當(dāng)在新的原型對象中沒有定義屬性constructor:Car時(shí),該原型對象的constructor指向Object。因此如下:
console.log(Car.prototype.constructor == Car); //false
console.log(Car.prototype); //Object
console.log(car2.__proto__); //Object
console.log(Object.getPrototypeOf(car2)); //Object
console.log(Car.prototype.constructor); //Object
console.log(car2.__proto__.constructor); //Object
console.log(Object.getPrototypeOf(car2).constructor); //Object
- 當(dāng)car2修改owner屬性為喬喬時(shí),此時(shí)并沒有修改原型對象中的owner屬性,只是給car2自身增加owner屬性,故car3的owner依舊是原型對象中的owner,為洋洋。
car2.owner = '喬喬';
console.log(car2.owner); //喬喬
console.log(car3.owner); //洋洋
console.log(car2.hasOwnProperty('owner')); //true
console.log(car3.hasOwnProperty('owner')); //false
- 當(dāng)其中一個(gè)實(shí)例修改原型對象中的引用類型的值時(shí),則共享數(shù)據(jù)的所有實(shí)例訪問原型對象中該值時(shí),均會(huì)改變。
