原型是函数的一个属性,是一个对象,如果函数作为构造函数使用,那么这个构造函数的所有实例,都共享这个原型对象。 那么我们原型有什么缺陷呢?原型的缺陷本质上就是共享的缺陷。下面举个栗子:
变量赋值于基本数据类型时
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 判断属性属否挂在实例上