注:
//定义一个父类
function Animal(){
/*动物类有什么特征和行为*/
this.name=null;
this.age=null;
this.sex=null;
this.sleep=function(){
return this.name+"在睡觉";
}
}
//原型链追加(继承) 给原型方法里面追加属性和行为的
Animal.prototype.eat=function(){
return this.name+"狗粮";
};
//定义一个子类
function Dog(){
this.play=function(){
return this.name+"正在玩球球";
}
}
一、原型链继承(单继承)
1.核心: 将父类的实例作为子类的原型继承。
2.特点:非常纯粹的继承关系,实例是子类也是父类的实例。父类新增原型方法/原型属性,子类都能访问到。
3.缺点:要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中无法实现多继承
创建子类实例时,无法向父类构造函数传参。
var a=new Animal(); //实例对象(造出一个新东西)
Dog.prototype=a; //D大写 dog对象中有了animal的所有属性
Dog.prototype.color=function(){
return this.name+"是白色";
}
//实例化Dog对象
var c=new Dog();
c.name="哦多都";
c.age="3";
c.sex="母";
console.log(c);
console.log(c.sleep());
console.log(c.play());
console.log(c.color());
console.log(c instanceof Animal); //判断C对象到A对象构造函数的类型是否一致
console.log(c instanceof Dog);
二、构造继承(多继承)
1.核心:父类的实例复制给子类(没用到原型)。
2.特点:创建子类实例时,可以向父类传递参数可以实现多继承(call多个父类对象)。
3.缺点:实例只是子类的实例只能继承父类的实例属性和方法,不能继承原型属性/方法,无法实现函数复用。每个子类都有父类实例函数的副本,影响性能。
function Animal(name,color,sex,age,type){
/*动物类有什么特征和行为*/
this.name=name;
this.AnimalColor=color;
this.sex=sex;
this.age=age;
this.type=type;
this.sleep=function (){
return this.name+"会睡觉";
}
}
Animal.prototype.solo=function (){
return "哈哈"
}
//另一个父类
function rou(name){
this.name=name;
this.eat=function (){
return this.name+"吃肉";
}
}
//定义一个子类对象
function Cat(name,color,sex,age,type){
Animal.call(this,name,color,sex,age,type);
rou.apply(this,[name]);
}
var c=new Cat("小猫","白色","母",2,"猫");
console.log(c);
console.log(c.eat());
console.log(c instanceof Cat);
console.log(c instanceof Animal);
console.log(c instanceof rou);
注:call和apply在替换上无区别,在参数上有区别。
Animal.call(this,name,color,sex,age,type);
rou.apply(this,[name]);
//定义一个父类
function Animal(){
this.name=null; //此this指animal 替换后指dog
}
//定义一个子类
function Dog(){
Animal.call(this); //用dog去替换animal中的所有对象 此this指dog 则替换后之前的this全部指dog而不是animal
Animal.apply(this);
//call和apply在替换上无区别,在参数上有区别
}
三、实例继承(单继承)
1.特点:不限制调用方式,不管是实例化对象,返回的对象具有相同的效果
2.缺点:实例是父类的实例,不是子类的实例,不支持多继承
/*先去定义一个父类对象*/
function Animal(){
/*动物类有什么特征和行为*/
this.name=null;
}
//定义一个子类对象
function Cat(){
var a=new Animal();
return a;
}
console.log(Cat());
//直接调用方法0或者实例化对象
var c=new Cat();
console.log(c);
/*先去定义一个父类对象*/
function Animal(){
/*动物类有什么特征和行为*/
this.name=null;
this.AnimalColor=null;
this.sex=null;
this.age=null;
this.type=null;
this.sleep=function (){
return this.name+"会睡觉";
}
}
Animal.prototype.speed=function (){
return 5.0;
}
//定义一个子类对象
function Cat(){
var a=new Animal();
a.name="小猫";
return a;
}
var c=new Cat();
console.log(c);
console.log(c.speed());
console.log(c instanceof Cat);
console.log(c instanceof Animal);
四、组合继承
原型链继承要放到子类实例之前。
/*先去定义一个父类对象*/
function Animal(){
/*动物类有什么特征和行为*/
this.name=null;
this.AnimalColor=null;
this.sex=null;
this.age=null;
this.type=null;
this.sleep=function (){
return this.name+"会睡觉";
}
}
Animal.prototype.speed=function (){
return 5.0;
}
//构造继承
function rou(){
this.eat=function (){
return "吃肉";
}
}
//定义一个子类对象
function Cat(){
Animal.call(this);
rou.call(this);
}
//构造继承无法继承原型属性/方法,所以写一个原型继承,可拿到speed
Cat.prototype=new Animal();
console.log(c.speed());
var c=new Cat();
console.log(c);
console.log(c.eat());