1.原型链继承
原型链继承是比较常见的继承方式之一,其中涉及的构造函数、原型和实例,三者之间存在着一定的关系,即每一个构造函数都有一个原型对象,原型对象又包含一个指向构造函数的指针,而实例则包含一个原型对象的指针
举个例子
functionParent(){this.name='parent1';this.play=[1,2,3]}functionChild(){this.type='child2';}Child1.prototype=newParent();console.log(newChild())
缺点:
多个实例对引用类型的操作会被篡改。
2.构造函数继承
借助 call
调用Parent
函数
functionParent(){this.name='parent1';}Parent.prototype.getName=function(){returnthis.name;}functionChild(){Parent1.call(this);this.type='child'}letchild=newChild();console.log(child);//没问题console.log(child.getName());//会报错
缺点:
只能继承父类的实例属性和方法,不能继承原型属性/方法
无法实现复用,每个子类都有父类实例函数的副本,影响性能
3.组合继承
前面我们讲到两种继承方式,各有优缺点。组合继承则将前两种方式继承起来
functionParent3(){this.name='parent3';this.play=[1,2,3];}Parent3.prototype.getName=function(){returnthis.name;}functionChild3(){//第二次调用Parent3()Parent3.call(this);this.type='child3';}//第一次调用Parent3()Child3.prototype=newParent3();//手动挂上构造器,指向自己的构造函数Child3.prototype.constructor=Child3;vars3=newChild3();vars4=newChild3();s3.play.push(4);console.log(s3.play,s4.play);//不互相影响console.log(s3.getName());//正常输出'parent3'console.log(s4.getName());//正常输出'parent3'
缺点:
会执行两次父类的构造函数,造成多构造一次的性能开销
4.原型式继承
这里主要借助Object.create
方法实现普通对象的继承
同样举个例子
letparent4={name:"parent4",friends:["p1","p2","p3"],getName:function(){returnthis.name;}};letperson4=Object.create(parent4);person4.name="tom";person4.friends.push("jerry");letperson5=Object.create(parent4);person5.friends.push("lucy");console.log(person4.name);//tomconsole.log(person4.name===person4.getName());//trueconsole.log(person5.name);//parent4console.log(person4.friends);//["p1","p2","p3","jerry","lucy"]console.log(person5.friends);//["p1","p2","p3","jerry","lucy"]
缺点:
因为Object.create
方法实现的是浅拷贝,多个实例的引用类型属性指向相同的内存,存在篡改的可能
5.寄生式继承
寄生式继承在上面继承基础上进行优化,利用这个浅拷贝的能力再进行增强,添加一些方法
letparent5={name:"parent5",friends:["p1","p2","p3"],getName:function(){returnthis.name;}};functionclone(original){letclone=Object.create(original);clone.getFriends=function(){returnthis.friends;};returnclone;}letperson5=clone(parent5);console.log(person5.getName());//parent5console.log(person5.getFriends());//["p1","p2","p3"]
其优缺点也很明显,跟上面讲的原型式继承一样
6.寄生组合式继承
寄生组合式继承,借助解决普通对象的继承问题的Object.create
方法,在前面几种继承方式的优缺点基础上进行改造,这也是所有继承方式里面相对最优的继承方式
functionParent(name){this.name=name;this.say=()=>{console.log(111);};}functionChildren(name){Parent.call(this);this.name=name;}Children.prototype=Object.create(Parent.prototype);Children.prototype.constructor=Children;
参考文献
web-interview/inherit.md at master · febobo/web-interview (github.com)