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