继承
一、原型链继承
function Box()
{
this.colors = ["red", "blue", "green"];
}
Box.prototype.Fun = function(){
};
function Boll(){
} //继承了SuperType
Boll.prototype = new Box(); //将Boll的prototype对象指向一个Box的实例
var instance1 = new Boll();
instance1.colors.push("black");
alert(instance1.colors);
var instance2 = new Boll();
alert(instance2.colors);
优点:能通过instanceOf和isPrototypeOf的检测
注意:给原型添加方法的语句一定要放在原型替换Ball.prototype = new Box();之后
缺点:(1)Box中的属性(不是方法)也变成了Box的prototype中的公用属性,
如上面例子中的color属性,可以同时被instance1和instance2修改
(2)创建子类型的时候,不能像父类型的构造函数中传递参数。
二、构造函数继承
function SuperType(){
this.colors = ["red", "blue", "green"];
}
function SubType(){
//继承了SuperType
SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors);
var instance2 = new SubType();
alert(instance2.colors);
function SuperType(name){
this.name = name;
}
function SubType(){
//继承了SuperType,同时还传递了参数
SuperType.call(this, "Nicholas");
//实例属性
this.age = 29;
}
var instance = new SubType();
alert(instance.name); //"Nicholas";
alert(instance.age); //29
原理:在子类型构造函数的内部调用超类型构造函数
优点:解决了superType中的私有属性变公有的问题,可以传递参数
缺点:方法在函数中定义,无法得到复用
特点 | 优点 | 缺点 | |
---|---|---|---|
原型链继承 | 子类原型prototype对父类实例化来实现 | 子类不仅仅可以访问父类原型上的属性和方法,同样也可以访问从父类构造函数中复制的属性和方法 | 1.一个子类原型更改子类原型从父类继承来的引用类型属性就会直接影响其他子类; 2.由于子类实现的继承是靠其原型对父类的实例化实现的,因此在创建父类的时候,是无法向父类传递参数的,因而在实例化父类时也无法对父类构造函数的属性进行初始化。 |
构造函数继承 | 在子类构造函数作用环境执行一次父类的构造函数实现 | 避免了引用类型的属性被所有实例共享,而且可以在子类中向父类传参 | 这种类型的继承没有涉及原型prototype,所以父类的原型方法自然不会被子类继承,而要想被子类继承就必须把放在构造函数里,这样创建出来的每个实例都会单独拥有一份而不能共用,这样就违背了代码复用的原则 |
三、组合继承
基于此,为了综合这两种模式的优点,就有了组合继承。
function Box(v){
this.v=v;
console.log(v);
}
Box.prototype.run=function(){
}
Box.prototype.a=10;
function Ball(v){
Box.call(this,v);//冒充继承
}
Ball.prototype=new Box();//将Boll的prototype对象指向一个Box的实例它相当于完全删除了prototype 对象原先的值,然后赋予一个新值
Object.defineProperty(Ball.prototype,"constructor",{
value:Ball
})//任何一个prototype对象都有一个constructor属性,指向它的构造函数。如果没有"Cat.prototype = new Animal();"这一行,Cat.prototype.constructor是指向Cat的;加了这一行以后,Cat.prototype.constructor指向Animal。
var c=new Ball(3);
console.log(c);
首先,在子类构造函数执行了父类构造函数,然后子类原型上实例化父类就是组合模式。如此,组合式继承就融合了原型链继承和构造函数继承的优点,并且过滤了其缺点。