首页>>前端>>JavaScript->JavaScript继承的6种方式复盘

JavaScript继承的6种方式复盘

时间:2023-11-30 本站 点击:0

前言

本篇谈一下关于JavaScript 继承相关的知识。包括继承的方式,已经一些优缺点等。本篇知识点获取来源红宝书。

继承方式

关于JavaScript 继承的方式,有大概的如下六种:

原型链继承;

借用构造函数继承;

组合继承;

原型式继承;

寄生式继承;

寄生组合式继承;

这里我们分别展开来讲解。

原型链继承

主要思想:

利用原型让一个引用类型继承另一个引用类型的属性和方法。

实现代码:

functionParent(){this.name='cook';}Parent.prototype.getName=function(){console.log(this.name)}functionChild(){this.age=1}constchild=newChild();console.log(child.getName())//'cook'

缺点:

引用类型的原型属性会被所有实例共享;

创建子类型的实例时(new Child()),不能向超类型的构造函数(Parent)中传递参数;

借用构造函数继承

借用构造函数也叫伪造对象或经典继承。

主要思想:

在子类型的构造函数的内部,调用超类型构造函数。

实现代码:

functionParent(name){this.colors=['red','blue','green'];this.name=name;}functionChild(name){//继承了Parent,并传递了参数Parent.call(this,name)}constchild1=newChild('james');child1.colors.push('pink');console.log(child1.colors);//['red','blue','green','pink']console.log(child1.name);//'james'constchild2=newChild('henry');console.log(child2.colors);//['red','blue','green']console.log(child2.name);//'henry'

优点:

避免引用类型的原型属性会被所有实例共享;

子类型的构造函数(Child)能向超类型构造函数(Parent)传递参数。

缺点:

方法都在构造函数中定义,无法函数复用(无法继承超类型的原型Parent.prototype定义的方法);

每次创建实例都会创建一遍方法(每new Child()一次,就会执行Parent.call(this, name));

组合继承

组合继承也叫伪经典继承。

主要思路:

使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承。

实现代码:

functionParent(name){this.colors=['red','blue','green'];this.name=name;}Parent.prototype.getName=function(){console.log(this.name)}functionChild(name,age){//继承了Parent,并传递了参数//通过借用构造函数来实现对实例属性的继承Parent.call(this,name)this.age=age;}//使用原型链实现对原型属性和方法的继承Child.prototype=newParent();Child.prototype.constructor=Child;constchild1=newChild('james',12);child1.colors.push('pink');console.log(child1.colors);//['red','blue','green','pink']console.log(child1.name);//'james'console.log(child1.age);//12constchild2=newChild('henry',15);console.log(child2.colors);//['red','blue','green']console.log(child2.name);//'henry'console.log(child2.age);//15

优点:

融合原型链继承和构造函数的优点,是 JavaScript 中最常用的继承模式。

避免引用类型的原型属性会被所有实例共享;

子类型的构造函数(Child)能向超类型构造函数(Parent)传递参数;

继承超类型的原型Parent.prototype定义的方法,实现函数复用;

缺点:

会调用两次父构造函数Parent

constchild1=newChild('james',12);//内部调用了Parent.call(this,name)

一次是设置子类型实例的原型的时候(Child.prototype = new Parent());

一次在创建子类型实例的时候;

存在实例属性过度赋值。使用 Child.prototype = new Parent(),导致Child.prototypechild1 都拥有构造函数实例的属性。

原型式继承

主要思路:

借助原型,基于已有的对象创建新对象。简单来说就是Object.create 的模拟实现。

实现代码:

functioncreate(o){functionF(){}F.prototype=o;returnnewF();}

缺点:

引用类型的原型属性会被所有实例共享,这点跟原型链继承一样。

constparent={colors:['red','blue','green'],age:1,}constchild1=create(parent);constchild2=create(parent);child1.age=18;console.log(child2.age);//1child1.colors.push('pink');console.log(child2.colors);//['red','blue','green','pink']

寄生式继承

主要思路:

创建一个仅用于封装继承过程的函数,该函数内部以某种方式来增强对象,最后返回对象。

实现代码:

functioncreateAnother(o){varclone=Object.create(o);clone.sayName=function(){console.log('hi');}returnclone;}

缺点:

跟借用构造函数模式一样,每次创建对象都会创建一遍方法。

寄生组合式继承

主要思路:

通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。本质上是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。

实现代码:

functioncreate(o){functionF(){}F.prototype=o;returnnewF();}functioninheritPrototype(child,parent){//使用寄生式继承来继承超类型的原型constprototype=create(parent.prototype);prototype.constructor=child;//将结果指定给子类型的原型child.prototype=prototype;}functionParent(name){this.colors=['red','blue','green'];this.name=name;}Parent.prototype.getName=function(){console.log(this.name)}functionChild(name,age){//通过借用构造函数来继承属性Parent.call(this,name)this.age=age;}//使用的时候:inheritPrototype(Child,Parent);

优点:

只调用了一次构造函数,避免了在Child.prototype上创建不必要的、多余的属性;

与此同时,原型链还能保持不变;

还能够正常使用 instanceof 和 isPrototypeOf。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/JavaScript/2586.html