首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >JavaScript中6种继承方式总结

JavaScript中6种继承方式总结

作者头像
henu_Newxc03
发布2022-05-05 18:14:07
发布2022-05-05 18:14:07
6410
举报

😎 原型链继承

第一种是以原型链的方式来实现继承,但是这种方式实现存在的缺点是,在包含引用类型的数据时,会被所有的实例对象所共享,容易造成修改的混乱,还有就是在创建子类型的时候不能向超类型传递参数。

代码语言:javascript
复制
  function Parent() {
    this.type = '赛亚人';
    this.skill = ['变身', '气功']
  }
  function Child() {
    this.name = '卡卡罗特';
  }
  Child.prototype = new Parent();
  console.log(new Child());
代码语言:javascript
复制
let goku1=new Child()
let goku2=new Child()
goku1.skill.push('瞬移');
console.log(goku1);
console.log(goku2);

我们在代码里的操作本意是只改变goku1的属性,但是为什么goku2的属性也被改变了呢?因为skill是一个数组,为引用类型,goku1与goku2的skill实际是指向同一块内存空间,因此修改会变得混乱。我们将在接下来的继承方式中解决这个问题。

🤓 构造函数继承

第二种方式是借用构造函数的方式,这种方式是通过在子类型的函数中调用超类型的构造函数来实现的,这一种方法解决了不能向超类型传递参数的缺点,但是它存在的一个问题就是无法实现函数方法的复用,并且超类型原型定义的方法子类型也没有办法访问到

代码语言:javascript
复制
  function Parent(){
    this.type = '赛亚人';
  }
 
  Parent.prototype.getType = function () {
    return this.type;
  }
 
  function Child(){
    Parent.call(this);
    this.name = '卡卡罗特'
  }
 
  let goku = new Child();
  console.log(goku);  // 正确
  console.log(goku.getType());  // 报错

我们发现这种构造函数的继承方式只能继承父类的实例属性和方法,不能继承原型属性或者方法。上述两种方式都各有优缺点,如果我们将两种方式结合一下就产生了组合继承。

😇 组合继承

第三种方式是组合继承,组合继承是将原型链和借用构造函数组合起来使用的一种方式。通过借用构造函数的方式来实现类型的属性的继承,通过将子类型的原型设置为超类型的实例来实现方法的继承。这种方式解决了上面的两种模式单独使用时的问题,但是由于我们是以超类型的实例来作为子类型的原型,所以调用了两次超类的构造函数,造成了子类型的原型中多了很多不必要的属性。

代码语言:javascript
复制
  function Parent() {
    this.type = '赛亚人';
    this.skill = ['变身', '气功']
  }
  Parent.prototype.getType = function () {
    return this.type;
  }
  function Child() {
    // 第二次调用 Parent()
    Parent.call(this);
    this.name = '卡卡罗特';
  }
 
  // 第一次调用 Parent()
  Child.prototype = new Parent();
  // 手动挂上构造器,指向自己的构造函数
  Child.prototype.constructor = Child;
  let goku1 = new Child();
  let goku2 = new Child();
  goku1.skill.push('瞬移');
  console.log(goku1.skill, goku2.skill);  // 不互相影响
  console.log(goku1.getType()); // 正常输出'赛亚人'
  console.log(goku2.getType()); // 正常输出'赛亚人'

在这里我们可以看出Parent()执行了两次,这必然会带来多余的性能开销,那我们怎么解决这个问题呢?此外,上述的三种方法都是围绕构造函数,那对于普通对象而言,怎么进行继承呢?

🥹 原型式继承

第四种方式是原型式继承,原型式继承的主要思路就是基于已有的对象来创建新的对象,实现的原理是,向函数中传入一个对象,然后返回以这个对象为原型的对象。这种继承的思路主要不是为了实现创造一种新的类型,只是对某个对象实现一种简单的继承,ES5中定义的Object.create()方法就是原型式继承的实现。缺点与原型链方式相同。

代码语言:javascript
复制
  let parent = {
    type: "赛亚人",
    skill: ["变身", "气功"],
    getType: function() {
      return this.type;
    }
  };
 
  let goku1 = Object.create(parent);
  goku1.name = "卡卡罗特";
  goku1.skill.push("瞬移");
  
  let goku2 = Object.create(parent);
  goku2.name = "悟空";
  goku2.skill.push("舞空术");
 
  console.log(goku1);
  console.log(goku2);

这种修改混乱的情况我们就不再赘述了,和第一种方式是同一个道理。

🥸 寄生式继承

第五种方式是寄生式继承,寄生式继承的思路是创建一个用于封装继承过程的函数,通过传入一个对象,然后复制一个对象的副本,然后对象进行拓展,最后返回这个对象。这个拓展的过程就可以理解是一种继承。这种继承的优点就是对一个简单对象实现继承,如果这个对象不是自定义类型时,缺点就是没办法实现函数的复用。

代码语言:javascript
复制
  let parent = {
    type: "赛亚人",
    skill: ["变身", "气功"],
    getType: function() {
      return this.type;
    }
  };
  function clone(original) {
    let clone = Object.create(original);
    clone.getSkill = function() {
      return this.skill
    };
    return clone;
  }
 
  let goku = clone(parent);
  console.log(goku.getType());
  console.log(goku.getSkill());

🧐 寄生组合式继承

第六种方式是寄生式组合继承,组合继承的缺点就是使用超类型的实例作为子类型的原型,导致添加了不必要的原型属性。寄生式组合继承的方式是 使用超类型的原型副本来作为子类型的原型,这样就避免了创建不必要的属性

代码语言:javascript
复制
  function clone (parent, child) {
    // 这里改用 Object.create 就可以减少组合继承中多进行一次构造的过程
    child.prototype = Object.create(parent.prototype);
    child.prototype.constructor = child;
  }
 
  function Parent() {
    this.type = '赛亚人';
    this.skill = ["变身", "气功"];
  }
   Parent.prototype.getType = function () {
    return this.type;
  }
  
  function Child() {
    Parent.call(this);
    this.name = '卡卡罗特';
  }
 
  clone(Parent, Child);
 
  Child.prototype.getName = function () {
    return this.name;
  }
 
  let goku  = new Child();
  console.log(goku);
  console.log(goku.getName());
  console.log(goku.getType());

寄生组合式继承是以上这六种里面最优的继承方式,基本上解决了上述继承方式的各种问题。

😋 总结

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-04-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 😎 原型链继承
  • 🤓 构造函数继承
  • 😇 组合继承
  • 🥹 原型式继承
  • 🥸 寄生式继承
  • 🧐 寄生组合式继承
  • 😋 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档