我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。即:通过调用构造函数而创建的那个对象实例的原型对象。
function Person(){};
Person.prototype.name='Nicholas';
Person.prototype.age=29;
Person.prototype.job='Software Engineer';
Person.prototype.sayName=function(){
alert(this.name);
};
var person1=new Person();
person1.sayName();//'Nicholas'
var person2=new Person();
person2.sayName();//'Nicholas'
alert(person1.sayName==person2.sayName);//true
理解原型对象
无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性。这个属性指向函数的原型对象。在默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性是一个指向prototype属性的指针。当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。ES5中,管这个指针叫[[Prototype]]。
虽然可以通过对象实例访问保存在原型中的值,但却不能通过对象实例重写原型中的值。如果在实例中添加了一个属性,而该属性与实例原型中的一个属性同名,那我们就在实例中创建该属性,该属性就会屏蔽原型中的那个属性。
function Person(){};
Person.prototype.name='Nicholas';
Person.prototype.age=29;
Person.prototype.job='Software Engineer';
Person.prototype.sayName=function(){
alert(this.name);
};
var person1=new Person();
var person2=new Person();
person1.name='Greg';
console.log(person1.name);//Gret
console.log(person2.name);//Nicholas
当为对象实例添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性;即添加这个属性只会阻止我们访问原型中的那个属性,但不会修改那个属性。即使将这个属性设置为null,也只会在实例中设置这个属性,而不会恢复其指向原型的连接。不过,使用delete操作符可以完全删除实例属性,从而能够重新访问原型中的属性。
更简单的原型语法:
可以将Person.prototype设置为等于一个以对象字面量形式创建的新对象
function Person(){}
Person.prototype={
name:'Nicholas',
age:29,
job:'Software Enhineer',
sayName:function(){
console.log(this.name);
}
};
这样写的话,Constructor属性不再指向Person了。当创建一个函数时,就会同时创建它的prototype对象,这个对象也会自动获得constructor属性。而采用对象字面量语法则本质上重写了默认的prototype对象,因此constructor属性也就变成了新对象的constructor属性(指向object构造函数),不再指向Person函数。
如果constructor的值很重要,可以再将其设置回适当的值
function Person(){}
Person.prototype={
constructor:Person,
name:'Nicholas',
age:29,
job:'Software Enhineer',
sayName:function(){
console.log(this.name);
}
};
原型的动态性:
由于在原型中查找值的过程是一次搜索,因此我们对原型对象所做的任何修改都能够立即从实例上反映出来。
var friend=new Person();
Person.prototype.sayHi=function(){
alert('Hi');
};
friend.sayHi();//'Hi'
但如果重写整个原型对象,情况就会不一样。调用构造函数时会为实例添加一个指向最初原型的[[prototype]]指针,而把原型修改为另一个对象就等于切断了构造函数与最初原型之间的联系。注意:实例中的指针仅指向原型,而不指向构造函数。
function Person(){};
var friend = new Person();
Person.prototype = {
constructor:Person,
name:'Nicholas',
age:29,
job:'Software Enhineer',
sayName:function(){
alert(this.name);
}
};
friend.sayName();//error