原型是函數的一個屬性,是一個對象,如果函數作爲構造函數使用,那麼這個構造函數的所有實例,都共享這個原型對象。
那麼我們原型有什麼缺陷呢?原型的缺陷本質上就是共享的缺陷。下面舉個栗子:
變量賦值於基本數據類型時
var age = 28;
var newAge = Age;
newAge = 31;
console.log(age,newAge); //28,31
當一個變量賦值於基本數據類型時,age和newAge在內存中是獨立的,互相不會影響。
變量賦值於引用數據類型
var color = [red,yellow];
var newColor = color;
newColor.push('blue');
console.log(color,newColor);//[red,yellow,blue],[red,yellow,blue]
此處的color和newColor同時引用了[red,yellow]這個數據,當newColor改變了這個數據後,當color訪問這個數據時,受到了影響,這個就是共享的問題,污染數據。
原型之下
我們在原型之下,看一段代碼:
function Zxf(){};
Zxf.prototype.tag= ['smart','cute'];
var zxf1 = new Zxf();
var zxf2 = new Zxf();
zxf1.tag.push('prefect');
console.log('zxf1',zxf1.tag); // ['zxf1','smart','cute','perfect'];
console.log('zxf2',zxf2.tag); // ['zxf2','smart','cute','perfect'];
通過代碼我們可以體會到,共享的缺陷,是原型創建對象嚴重的缺陷。
當然還有其他的缺陷,比如不能傳參。
構造函數結合原型
那怎樣纔算是“完美的”原型呢?——構造函數結合原型
- 構造函數獨有屬性
- 原型共享方法
function Zxf(name,age,isNice){
this.name = name;
this.age = age;
this.isNice = isNice
}
Zxf.prototype.showName = function(){
console.log(this.name)
}
var zxf1 = new Zxf('Amber','18',true);
var zxf2 = new Zxf('Alex','18',true);
zxf1.showName(); //Amber
zxf2.showName(); //Alex
構造函數結合原型的2個操作
- 屬性的覆蓋和查找:實例裏的屬性會覆蓋掉原型上的屬性
- 屬性的判斷:in操作符 & hasOwnProperty
判斷屬性到底存在於哪個地方,我們使用in操作符和hasOwnProperty:
(我們還使用上段代碼)
console.log('name' in zxf1);
//返回tru-e,只要name在對象中,不管是在實例中還是原型上,都返回 t-rue
console.log(zxf1.hasOwnProperty('name')) //true 判斷屬性屬否掛在實例上