原型(prototype)
JavaScript中每一个对象(null除外)都和另一个对象相关联,被关联的对象就叫做 原型,每一个对象都从原型继承属性,所有通过对象直接量创建的对象都具有一个原型对象,代码中可以使用 Object.prototype 获得原型对象的引用,通过new关键字和构造函数创建出来的对象的原型就是构造函数的prototype属性的值。例如:通过new Object()创建的对象的原型就是Object.prototype,new Array()创建的对象原型就是Array.prototype。
原型链
JavaScript中没有原型的对象很少,例如:Object.prototype,该对象不继承任何属性,其他的原型对象都是普通对象,普通对象都具有原型,所有的内置构造函数以及大部分自定的构造函数都具有一个继承自Object.prototype的原型,例如:Array.prototype的属性继承自Object.prototype,因此有new Array()创建的Array对象的属性同时继承Object.prototype和Array.prototype,这一系列链接的原型就叫做 原型链(prototype chain) 。
原型继承
var Person = function() { //Person原型对象
this.canTalk = true;
this.greet = function() {
if (this.canTalk) {
console.log('Hi, I\'m ' + this.name);
}
};
};
var Employee = function(name, title) {//定义一个新的Employee 对象
this.name = name;
this.title = title;
this.greet = function() {
if (this.canTalk) {
console.log("Hi, I'm " + this.name + ", the " + this.title);
}
};
};
Employee.prototype = new Person();//Employee 对象继承Person对象以及它的属性
var Customer = function(name) {
this.name = name;
};
Customer.prototype = new Person();//Customer 对象继承Person对象以及它的属性
var Mime = function(name) {
this.name = name;
this.canTalk = false;
};
Mime.prototype = new Person();//Mime 对象继承Person对象以及它的属性
var bob = new Employee('Bob', 'Builder');
var joe = new Customer('Joe');
var rg = new Employee('Red Green', 'Handyman');
var mike = new Customer('Mike');
var mime = new Mime('Mime');
/**
* 调用继承自Person对象中的方法
*/
bob.greet();
joe.greet();
rg.greet();
mike.greet();
mime.greet();
/*输出结果:
Hi, I'm Bob, the Builder
Hi, I'm Joe
Hi, I'm Red Green, the Handyman
Hi, I'm Mike
*/
原型链
var Person = function(){//Person对象原型,继承自Object对象
this.talk = function(){
console.log("Hi,I\'m Person " + this.name);
}
};
var Woman = function(){//Woman 对象
this.talkNameAndSex = function(){
console.log("Hi,I\'m Woman " + this.name + ",sex " + this.sex);
}
};
Woman.prototype = new Person();//Woman对象继承Person对象同时也会继承Object对象
var Gril = function(name,sex){//Gril 对象
this.name = name,
this.sex = sex,
this.talkSelf = function(){
console.log("Hi,I\'m gril " + this.name + ",sex " + this.sex);
}
};
Gril.prototype = new Woman();//Gril对象继承Woman对象同时也会继承Object对象和Person对象
var youngGril = new Gril("Tom","Woman");//创建对象实例
console.log(youngGril);//控制台输出对象结构,见下图
youngGril.talkSelf();//调用Gril对象自身的方法
youngGril.talkNameAndSex();//调用Woman对象的方法
youngGril.talk();//调用Person对象的方法
/*
输出结果:
Hi,I'm gril Tom,sex Woman
Hi,I'm Woman Tom,sex Woman
Hi,I'm Person Tom
*/
对象的扩充
JavaScript中基于原型的继承机制是动态的:对象从原型中继承属性,如果创建对象之后原型属性发生改变,也会影响到这个原型的所有实例对象。这意味着可以通过给原型对象添加新的方法来扩充JavaScript类。
基于上面的例子
/**
* 给Person对象扩充一个sayHello的方法
*/
Person.prototype.sayHello = function(){
console.log("Hello I'm Person");
}
youngGril.sayHello();//调用原型扩充的方法
//输出结果:Hello I'm Person