对象继承
对象继承是最简单的继承类型。就是指定哪个对象是新对象的[[Prototyep]]。对象字面形式会隐式的指定Object.prototype为其[[Prototyep]],也可以用Object.create()方法显式指定。
Object.create()方法接受两个参数,第一个参数是需要被设置为新对象的[[Prototyep]]的对象;第二个是可选参数,是一个属性描述对象,使用格式和Object.defineProperties()方法一样。
var person1 = {
name:'Nicholas',
sayName:function(){
console.log(this.name);
}
}
var person2 = Object.create(person1,{
name:{
configurable:true,
enumerable:true,
value:'Greg',
writable:true
}
})
person1.sayName();//Nicholas
person2.sayName();//Greg
console.log(person1.hasOwnProperty('sayName'));//true
console.log(person1.isPrototypeOf(person2));//true
console.log(person2.hasOwnProperty('sayName'));//false

var nakedObj = Object.create(null);
console.log('toString' in nakedObj);//false
console.log('valueOf' in nakedObj);//false
nakedObj是一个没有原型对象链的对象,意味着toString()和valueOf()登内建方法都不在该对象上。
构造函数继承
一个简单的例子:
function YourConstructor(){
//
}
YourConstructor.prototype = Object.create(Object.prototype,{
constructor:{
configurable:true,
enumerable:true,
value:YourConstructor,
writable:true
}
})
这段代码把构造函数的prototype属性设置为一个继承自Object.prototype的对象,这意味着YourConstructor创建出来的任何对象都继承自Object.prototype;YourConstructor是Object的之类,而Object是YourConstructor的父类。 思考下面这个例子:
function Rectangle(length,width){
this.length = length;
this.width = width;
}
// Rectangle.prototype.getArea = function(){
// return this.length*this.width;
// }
// Rectangle.prototype.toString = function(){
// return "[Rectangle"+this.length+"X"+this.width+"]";
// }
Rectangle.prototype = {
getArea:function(){
return this.length*this.width;
},
toString:function(){
return "[Rectangle"+this.length+"X"+this.width+"]";
}
}
//inherits from Rectangle
function Square(size){
this.length = size;
this.width = size;
}
Square.prototype = new Rectangle();
Square.prototype.constructor = Square;
Square.prototype.toString = function(){
return "[Square"+this.length+"X"+this.width+"]";
}
var rect = new Rectangle(5,10);
var square = new Square(6);
console.log(rect.getArea());//50;
console.log(square.getArea());//36
console.log(rect.toString());//[Rectangle5X10]
console.log(square.toString());//[Square6X6]
console.log(rect instanceof Rectangle);//true
console.log(rect instanceof Object);//true
console.log(square instanceof Square);//true
console.log(square instanceof Object);//true
console.log(square instanceof Rectangle);//true
这段代码里创造了两个构造函数:Rectangle和Square。Square构造函数的prototype属性被改写为Rectangle的一个对象实例。此时不需要给Rectangle的调用提供参数,因为它们不需要被使用,而且如果提供了,那么所有的Square的对象实例都会共享同样的维度。

//inherits from Rectangle
function Square(size){
this.length = size;
this.width = size;
}
Square.prototype = Object.create(Rectangle.prototype,{
constructor:{
configurable:true,
enumerable:true,
value:Square,
writable:true
}
})
Square.prototype.toString = function(){
return "[Square"+this.length+"X"+this.width+"]";
}
var rect = new Rectangle(5,10);
var square = new Square(6);
console.log(rect.getArea());//50;
console.log(square.getArea());//36
console.log(rect.toString());//[Rectangle5X10]
console.log(square.toString());//[Square6X6]
console.log(rect instanceof Rectangle);//true
console.log(rect instanceof Object);//true
console.log(square instanceof Square);//true
console.log(square instanceof Object);//true
console.log(square instanceof Rectangle);//true
注意: 在对原型对象添加属性前要确保你已经修改了原型对象,否则在改写时会丢失之前添加的方法。 构造函数的窃取 构造函数的窃取,通常也称为伪类继承。构造函数窃取的关键就是在于this。只要在子类给构造函数中用**call()或applay()**调用父类的构造函数,并将新创建的对象传进去即可。实际上、就是用自己的对象窃取父类的构造函数,如下例子:
function Square(size){
Rectangle.call(this,size,size);
}
Square.prototype = Object.create(Rectangle.prototype,{
constructor:{
configurable:true,
enumerable:true,
value:Square,
writable:true
}
})
Square.prototype.toString = function(){
return "[Square"+this.length+"X"+this.width+"]";
}
var square = new Square(6);
console.log(square.getArea());//36
console.log(square.toString());//[Square6X6]
console.log(square.length);//6
console.log(square.width);//6
console.log(square instanceof Square);//true
console.log(square instanceof Object);//true
console.log(square instanceof Rectangle);//true
总结 JavaScrip通过原型对象链支持继承。当将一个对象的[[Prototype]]设置为另一个对象时,就在这两个对象之间创建了一条原型对象链。所有的泛用对象都自动继承自Object.prototype。如果想要创建一个继承自其他对象的对象,可以用Object.create()指定[[Prototype]]为一个新对象。 可以在构造函数中创建原型对象链来完成自定义类型之间的继承。通过将构造函数的prototype属性设置为某一个对象,就像建立自定义类型对象和该对象的继承关系。构造函数的所有对象实例共享同一个原型对象,所以他们都继承自该对象。 为了正确继承自由属性,可以使用构造函数窃取。只需call()和apply()调用父类的构造函数,就可以在之类里完成各种初始化。结合构造函数窃取和原型对象链是JavaScript中最常见的继承手段,由于和基于类的继承相似,这个组合经常被称为为类继承。