《JavaScript高级程序设计》中涉及到的继承方式:原型链,借用构造函数,组合继承,原型式继承,寄生式继承,寄生组合式继承。
没关系,我当时看完第一遍也是实力懵逼。后来反反复复学了好多遍,总算搞清楚了(特别是寄生组合式继成。)接下来就尽量用浅显易懂的方式总结一遍。
一.原型链:
原型我就不过多介绍了,有时间会写博客总结。
先说说重写原型对象。什么是重写原型对象?就是以对象字面量的形式来重新定义原型对象的属性和方法。
比如:
function Person{
}
Person.prototype = {
name : "Nico",
age : 20,
job : "FE",
sayName : function(){
alert(this.name);
}
}
以上以对象字面量重写原型对象之后,原型对象的constructor不再指向Person了。因为每创建一个函数,就会同时创建它的prototype对象,这个对象也自动获得constructor属性,因此,新的原型对象的constructor现在指向Object构造函数,可以通过constructor:Person这么一句增强对象。不过这样会将它的[[Enumerable]]特性设置为true,可以通过Object.defineProperty()来设置。具体就不做扩展了。
这里特地提到是因为要告诉米娜桑,如果创建实例之后重新了原型对象,实例仍指向最初的原型对象。所以实例使无法调用新添加的方法和属性的。所以,在通过原型链实现继承时,不能使用对象字面量创建原型方法。
好了继续说原型链继承。实现方式是让原型对象等于另一个类型的实例。结果会怎样?此时的原型对象包含指向另一个原型的指针[[prototype]],相应地,另一个原型中也包含着一个指向另一个构造函数的指针constructor。如此以来层层递进,构成了实例与原型的链条。
先看一个例子。
function superType(){
this.property = true;
}
superType.prototype.getSuperValue = function(){
return this.property;
}
function subType(){
this.subproperty = false;
}
//继承了superType
subType.prototype = new superType();
subType.prototype.getSubValue = function(){
return this.subProperty;
}
var instance = new subValue();
alert(instance.getSuperValue);
以上的代码没有使用subType默认提供的原型,而是给它换了一个新原型,即superType的实例。如此一来,superType的所有的实例属性和实例方法被添加到subType的原型对象之中,因为此时subType的原型是superType的实例,所以实例属性和方法自然而然会被添加到实例之中。subType的原型对象也会多出一个[[prototype]]属性指向superType,这样形成一个原型链,实例instance访问getSuperType()方法时,会经过三个步骤:(1)搜索实例,(2)搜索subType.prototype,(3)搜索superType.prototype。搜索过程是一环一环前行到原型链末端才会停下来。(注意,instance.constructor现在指向的是superType,因为subType的原型指向了另一个对象——superType的原型,而superType的原型的constructor指向的是superType。)
二.别忘记默认的原型:
所有函数的默认原型都是Object的实例,因此默认原型都会包含一个内部指针,指向Object.prototype。
三.确定原型和实例的关系:
1>使用instanceof()操作符。只要用这个操作符来测试实例与原型链中出现过的构造函数,结果就会返回true。
alert(instance instanceof Object) //true
alert(instance instanceof superType) //true
alert(instance insatanceof subType) //true
2>使用isPrototypeOf()方法。只要是原型链中出现过的原型,都可以说是该原型链所派生的实例的原型。
alert(Object.prototype.isPrototypeOf(instance)) //true
alert(superType.prototype.isPrototypeOf(instance)) //true
alert(subType.prototype.isPrototypeOf(instance)) //true
四.原型链的问题
1>包含引用类型值的原型属性会被所有实例共享。
2>在创建子类型的实例时,不能向超类型的构造函数中传递参数。