我们创建的每个函数都有一个 prototype(原型)属性,这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法。逻辑上可以这么理解:prototype 通过调用构造函数而创建的那个对象的原型对象。 使用原型的好处可以让所有对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中定义对象信息,而是可以直接将这些信息添加到原型中。
function Human(name,age,work) {
this.name = name;
this.age = age;
this.work = function() {
return work;
};
}
var man1 = new Human('paul',31,'打篮球');
alert(man1.work());
var man2 = new Human('wade',34,'打篮球');
alert(man2.work());
alert(man1.work == man2.work)//false
function Human() {}
Human.prototype.name = 'paul';
Human.prototype.age = 31;
Human.prototype.work = function(){
return '打篮球';
};
var man1 = new Human();
alert(man1.name)//paul
var man2 = new Human();
alert(man2.name);//paul
alert(man1.work == man2.work);//true
为了更进一步了解构造函数的声明方式和原型模式的声明方式, 我们通过图示来了解一下:
在原型模式声明中,多了两个属性,这两个属性都是创建对象时自动生成的。__proto__属性是实例指向原型对象的一个指针,它的作用就是指向构造函数的原型属性 constructor 。通过这两个属性,就可以访问到原型里的属性和方法了。
原型模式的执行流程:
1.先查找构造函数实例里的属性或方法,如果有,立刻返回;
2.如果构造函数实例里没有,则去它的原型对象里找,如果有,就返回;
虽然我们可以通过对象实例访问保存在原型中的值, 但却不能访问通过对象实例重写原型中的值。
function Car() {
}
Car.prototype.name = '布加迪威龙';
var car = new Car();
alert(car.name);//布加迪威龙
car.name = '奔驰';
alert(car.name);//奔驰
var car2 = new Car();
alert(car2.name);// 布加迪威龙
delete car.name;
alert(car.name);//布加迪威龙
如何判断属性是在构造函数的实例里,还是在原型里?可以使用 hasOwnProperty()函数来验证:实例中有此属性则返回true,否则false
function Car() {
this.type = '豪车'
}
Car.prototype.name = '布加迪威龙';
var car1 = new Car();
alert(car1.hasOwnProperty('name'))//false
alert(car1.hasOwnProperty('type'))//true
in 操作符会在通过对象能够访问给定属性时返回 true, 无论该属性存在于实例中还是原型中。
function Car() {
this.type = '豪车'
}
Car.prototype.name = '布加迪威龙';
var car1 = new Car();
alert(car1.hasOwnProperty('name'))//false
alert(car1.hasOwnProperty('type'))//true
alert('name' in car1);//true
alert('type' in car1);//true
通过hasOwnPrototy() 和 in 操作符可以判断某个属性是否在原型中
function Car() {
this.type = '豪车'
}
Car.prototype.name = '布加迪威龙';
var car = new Car();
function isPrototype(obj,prototy) {
return !(obj.hasOwnProperty(prototy)) && (prototy in obj);
}
alert(isPrototype(car,'name'));//true
alert(isPrototype(car,'type'));//false