javascript 7种继承-- 寄生式继承分析(5)

概要

这阵子在整理JS的7种继承方式,发现很多文章跟视频,讲解后都不能让自己理解清晰,索性自己记录一下,希望个位发表需要修改的意见,共勉之。
部分文章总结出来的数据可能是错误的,网络上太多数据了,有些不严谨,当然我也可能是其中一人,如果有问题,欢迎提出来,共同进步。


javascript 7种继承 文章导航
由于避免篇幅过长导致阅读疲倦等原因,这边进行内容拆解成专栏,并且添加了导航。
:)

文章名
1new操作符的原理以及实现
2[[Prototype]] 与 proto 与 .prototype
31. 原型链继承分析
42. 构造函数继承分析
53. 组合式继承分析
64. 原型式继承分析
75. 寄生式继承分析
86. 寄生组合式继承
97. class继承

继承的进化史

JS的7种并不是逐级进化的(个人觉得~),可以参考下图:

在这里插入图片描述

技术名词解释

  • 原型式继承:返回一个空的构造函数所创建的实例,并该构造函数的prototype指向需要继承的对象,说白了就是直接浅拷贝copy一个新的对象给你用,可以参考原型式继承的一句话代码:let parent2 = Object.create(obj);
  • 工厂模式:定义一个创建对象的方法,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

寄生式继承

说的寄生式继承,不得不提到上一篇文章的原型式继承,因为原型式继承无法传参,对父类部分属性重写只能在上下文中,通过 .操作符操作。而寄生式继承就是封装好一个函数,对原型式继承的实例化对象进行再加工,也是通过.操作符,不过环境上下文切换到了函数。这个也就是我们熟悉的设计模式之一工厂模式,既美化了代码,也实现了复用。

即原型式继承+工厂模式=寄生式继承


案列分析

  • 父类:parentObj,要被继承的对象,可以理解为人。
  • 子类:childrenFactory,创建子类的工厂,不同的工厂,可以代表不同的工种或者说是职业。
  • 实例:person1 ,person2,实例化的子类,一般实例化后数据就分开了,复合数据类型要注意…

父类属性:

  1. name:父类属性,每个人都有名字 基础数据类型
  2. data:父类属性,个人的一些数据 复合数据类型,可以理解为个人的收藏,有人喜欢红酒,有人喜欢首饰 这里有BUG,数据混乱问题。
  3. sayData:父类方法,用来打印等下误操作的数据问题,打印BUG的地方,这边直接打印复合对象里面单独的属性,因为如果直接打印data,则永远指向最新的内存区域,也就是最后面修改的值,看不出变化…
  4. setData:父类方法,用于修改 data.a ,为了查看数据混乱。
  5. job:子类属性,代表工作,这里用于展示子类自带属性的一个实现,就是父子类总要有区别的嘛~
  6. sayJob:子类方法,用于打印工作内容。

源代码解析

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>寄生式继承</title>
  </head>
  <body>
    <h3>寄生式继承</h3>
    <h4>
      上一章节:原型式继承,里面对父类的重写都是放在上下文中通过
      .操作符来进行的,不是特别优雅。
    </h4>
    <h4>
      寄生式继承,就是在原型式继承基础上,通过一个函数对齐进行封装,而这类函数也是属于设计模式之一的工厂模式。
    </h4>
    <h4>优化:相对于原型式继承,可以传参。</h4>
    <h4>缺点:对象如果是复合数据类型的数据,会造成数据混乱。</h4>
    <script>
      let parentObj = {
        name: "未初始化的人",
        data: {
          a: 1,
          b: 2,
          c: 3,
        },
        sayData: function () {
          // 这里还不能直接打印对象出来,因为是一个指针,总是指向最新的数据...
          console.log(this.name +  " 的数据如下:");
          console.dir(this.data.a);
          console.dir(this.data.b);
          console.dir(this.data.c);
          console.log("我的数据结束====");
        },
        setDataA: function () {
          this.data.a = 666;
        },
      };

      // 这边仅使用Object.create() 来实现,避免代码量过多。
      function childrenFactory(name, job) {
        // 这里返回的是一个空的对象,obj放在了原型上了,所以只能修改temp中的数据。
        let temp = Object.create(parentObj);
        temp.name = name;
        temp.job = job ? job : "没工作";
        temp.sayJob = function () {
          console.log(`${this.name} 的工作是 ${this.job} ...`);
        };
        return temp;
      }

      let person1 = childrenFactory("钟先生", "程序员");
      let person2 = childrenFactory("刘小姐", "清洁阿姨");

      // 未修改数据
      console.log("===未修改数据的时候...");
      person1.sayData();
      person2.sayData();

      console.log("===修改钟先生一个人的数据的时候...");
      person1.setDataA();
      person1.sayData();
      person2.sayData();

      console.log(person1);
      console.log(person2);
    </script>
  </body>
</html>

效果图

部分同学不知道哪里修改了数据,这边贴上上方源码部分修改代码!

sayData: function () {
 // 这里还不能直接打印对象出来,因为是一个指针,总是指向最新的数据...
  console.log(this.name +  " 的数据如下:");
  console.dir(this.data.a);
  console.dir(this.data.b);
  console.dir(this.data.c);
  console.log("我的数据结束====");
}

console.log("===修改钟先生一个人的数据的时候...");
person1.setDataA();  // 就是这一句。
person1.sayData();
person2.sayData();

在这里插入图片描述
在这里插入图片描述

小结

  • 优化:相对于原型式继承,通过工厂模式,行进了更好的封装,由于有了函数,也实现了复用。
  • 缺点:原型链继承,原型式继承,寄生式继承,都存放复合数据类型数据混乱问题。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Penk是个码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值