继承


继承

//父类
function Person(name){//给构造函数添加了参数
this.name=name;
this.son=function(){
alert(this.name)
}
}
Person.prototype.age=10;//给构造函数添加了原型属性

1)原型链继承:让新实例的原型等于父类的实例

特点:新实例无法像父类构造函数传参、所有新实例都会共享父类实例的属性、新实例不会继承父类实例的属性

//原型链继承
function Per(){
this.name="ker"
}
Per.prototype=new Person();
var per1=new Per();
console.log(per1.age);//10
//per1继承了Person的属性
console.log(per1 instanceof Person);//true

2)借用构造函数继承:用call()和apply()将父类引入子类函数

特点:只能继承父类构造函数的属性不继承父类原型的属性、可以继承多个构造函数的属性、无法实现构造函数的复用、每个新实例都有父类构造函数的副本

//借用构造函数继承
function Con(){
Person.call(this,"jer")
this.age=12;
}
var con1=new Con();
console.log(con1.name)//"jer"
console.log(con1.age)//12
console.log(con1 instanceof Person)//false

3)组合式继承:结合了原型链继承和借用构造函数继承

特点:可以继承父类原型上的属性、可以进行传参和复用、每个新实例引入的构造函数属性都是私有的、调用了两次父类构造函数,子类的构造函数会代替原型上的父类构造函数

//组合式继承
function SubType(name){
Person.call(this,name)//借用构造函数模式
}
SubType.prototype=new Person();//原型链继承
var sub=new SubType("gar");
console.log(sub.name)//“gar”继承了构造函数属性
console.log(sub.age)//10 继承了父类原型的属性

4)原型式继承:用函数包装一个对象,然后返回这个函数的调用

特点:类似于赋值一个对象用函数来包装、所有实例都会继承原型上的属性、无法实现复用

//先封装一个函数容器,用来输出对象和承载继承的原型
function content(obj){
function F(){}
F.prototype=obj;//继承了传入的参数
return new F();//返回函数对象
}
var sup=new Person();//拿到父类的实例
var sup1=content(sup);
console.log(sup1.age);//10 继承了父类函数的属性

5)寄生式继承:给原型式继承外面套了个壳子

特点:没有创建自定义类型、没有用到原型、无法复用

function content(obj){
function F(){}
F.prototype=obj;//继承了传入的参数
return new F();//返回函数对象
}
var sup=new Person();//拿到父类的实例
//以上是原型式继承

6)寄生组合式继承:在函数内返回对象然后调用

特点:函数的原型等于另一个实例、在函数中用apply或者call引入另一个构造函数、可传参、修复了组合继承的问题

//寄生
function content(obj){
function F(){}
F.prototype=obj;
return new F();
}
//content就是F实例的另一种表示法
var con=content(Person.prototype)
//con实例(F实例)的原型继承了父类函数的原型
//上述更像是原型链继承,只不过只继承了原型属性
?
//组合
function Sub(){
Person.call(this)//这个继承解决了父类构造函数的属性
}//解决了组合式两次调用构造函数属性的缺点
Sub.prototype=con;//继承了con实例
con.constructor=Sub;//一定要修复实例
var sub1=new Sub();
//Sub的实例就继承了构造函数属性,父类实例,con的函数属性
console.log(sub1.age)//10
全文由作者ranyonsue的博客整理,本文仅作自己学习所用