罕用的继承形式

1:原型链继承

function Child(){    this.age="10";}function Father(){    this.name="father";    this.friends=['a','b'];}Father.prototype.sayName=function(){    console.log(this.name);}Child.prototype=new Father();Child.prototype.constructor=Child;var c1=new Child();var c2=new Child();c2.friends.push('c');/**顾名思义通过原型prototype对象进行继承,原型链向上查找公共属性办法.Child.prototype指向了Father实例毛病:1:无奈向父类传递参数用于结构。2:父类的name,firends公有属性,都成子类原型私有属性。c2.friends.push('c');执行后c1.firends也被批改 c2.friends==c1.friends==['a','b','c']*/

2:构造函数继承

function Child(data){    this.age="10";    Father.call(this,data)}function Father(data){    this.name=data.name;    this.friends=data.friends;    this.sayName=function(){        console.log(this.name)    }    console.log("被执行了")    }Father.prototype.showFriends=function(){    console.log(this.showFriends);}var c1=new Child({    name:'c1',    friends:['a','b']})var c2=new Child({    name:'c2',    friends:['c','d']})c1.friends.push('x')c2.friends.push('y')/**通过call|apply进行继承(属性拷贝),与prototype没有关系能够向子类传递结构参数,子类继承的父类属性独立.实现所有属性办法独享.毛病:1:雷同公共办法sayName没抽离,所有子类都有本人独立的sayName,(c1.sayName===c2.sayName)false*/

3:原型继承+call继承(组合继承)

function Child(data){    Father.call(this,data)}function Father(data){    this.name=data?data.name:"father";    this.friends=data?data.friends:[];    console.log("Father构造函数执行了")}Father.prototype.showFriends=function(){    console.log(this.friends)}Child.prototype=new Father();Child.prototype.constructor=Child;var c1=new Child({    name:'c1',    friends:['a','b']})var c2=new Child({    name:'c2',    friends:['c','d']})c1.friends.push('x')c2.friends.push('y')c1.showFriends()c2.showFriends()/**公有属性构造函数继承,公共属性办法原型链实现。毛病:1:调用了两次父类构造函数,生成了两份实例Father.call,Child.prototype=new Father();*/

4:寄生式继承

function createObj(o){    function F(){    }    F.prototype=o;    return new F();}function Child(data){    Father.call(this,data)}function Father(data){    this.name=data?data.name:"father";    this.friends=data?data.friends:[];    console.log("Father构造函数执行了")}Father.prototype.showFriends=function(){    console.log(this.friends)}Father.prototype.likes=['吃','睡'];Child.prototype=createObj(Father.prototype);Child.prototype.constructor=Child;Child.prototype.childLikes=function(){    console.log('aaa')}var c1=new Child({    name:"c1",    friends:['a','b']})var c2=new Child({    name:"c2",    friends:['c','d']})var f1=new Father({    name:"f1",    friends:['e','f']})c1.friends.push('x')c2.friends.push('y')console.log(c1,c2);/**应用两头空对象F来连接子类与父类,子类原型指向F实例F.prototype==Father.prototype,F没有公有属性因而new开销比拟小。*/

5:Class继承

class Father{    constructor(data){        this.name=data?data.name:"father";        this.friends=data?data.friends:[];    }    showFriends(){        console.log(this.friends)    }}class Child extends Father{    constructor(data){        super(data);    }}var c1=new Child({    name:'c1',    friends:['a','b']})var c2=new Child({    name:'c2',    friends:['c','d']})c1.friends.push('x')c2.friends.push('y')console.log(c1,c2)/**和寄生式继承成果一样,简洁语义更好。子类构造函数必须先调用一次super*/