首先来讨论一下原型链,上代码
1 function SuperType(){ 2 this.property = true; 3 } 4 5 SuperType.prototype.getSuperValue = function(){ 6 console.log(this.property); 7 } 8 9 function SubType(){ 10 this.subproperty = false; 11 } 12 13 SubType.prototype = new SuperType(); 14 15 SubType.prototype.getSubValue = function(){ 16 console.log(this.subproperty); 17 } 18 19 var instance = new SubType(); 20 21 console.log(instance.getSuperValue());//true
前三行创建了一个名为SuperType的构造器,并为其添加了一个属性propertype,其值设为true,然后在SuperType的原型上添加方法getSuperValue,功能是输出属性property的值,第一个构造函数完毕。9到11行创建第二个构造函数并添加属性subproperty,其值设为false。重点部分:第13行,把一个SuperType的实例赋值给SubType的原型。后面同样为SubType的原型添加一个方法。然后创建一个Subtype的实例,调用getSuperValue方法,返回true。
下面来仔细分析一下这条原型链,首先创造一个构造函数SuperType,它指向自己的原型,而原型的constructor有指向SuperType,这是第一部分,第二次创造了新的构造函数SubType,它的实例instance指向它的原型,而它的原型已经被设定为一个SuperType的实例,而这个实例又指向SuperType的原型,所以这部分和刚刚的第一部分就联系起来了,问题来了,instance。constructor是谁?沿着刚刚说的原型链向上找,
console.log(instance.constructor);//SuperType
同理,SuperType其实还能沿着原型链向上,上面就是Object。
第二种:借用构造函数,上代码:
1 function SuperType(name){ 2 this.name = name; 3 } 4 5 function SubType(){ 6 SuperType.call(this,"jiangjie"); 7 this.age = 20; 8 } 9 10 var instance = new SubType(); 11 12 console.log(instance.name);//jiangjie 13 console.log(instance.age);//20 14 15 console.log(instance.constructor);//Subtype 16 console.log(Object.getPrototypeOf(instance)==SubType.prototype);//true 17 18 console.log(instance.hasOwnProperty("name"));//true
这样的写法就更容易理解了,使用call只是使用了Supertype的属性,但是并没有改动任何的原型链,我们可以使用hasOwnProperty来证明并不是调用了SuperType作为原型,
第三种:组合继承,上代码
1 function SuperType(name){ 2 this.color = ['red','black','white']; 3 this.name = name; 4 } 5 6 7 SuperType.prototype.sayName = function(){ 8 console.log(this.name); 9 } 10 11 function SubType(name,age){ 12 SuperType.call(this,name); 13 this.age = age; 14 } 15 16 SubType.prototype = new SuperType(); 17 18 SubType.prototype.sayAge = function(){ 19 console.log(this.age); 20 } 21 22 var instance1 = new SubType('jaingjie','20'); 23 var instance2 = new SubType('lukexin','20'); 24 25 instance1.color.push('green'); 26 console.log(instance1.color);//['red','black','white','green']; 27 console.log(instance1.sayName());//jiangjie 28 console.log(instance1.sayAge());//20 29 30 console.log(instance2.color);//['red','black','white']; 31 console.log(instance2.sayName());//lukexin 32 console.log(instance2.sayAge());//20
说白了就是改进版,集中各个方法所长,使用 借用构造函数 方法,来设定各自实例属性,通过原型来设定通用的方法,但是要注意,为了确保构造函数不会重写子类的属性,要在调用超类型构造函数以后,再为子类添加属性