javascript 7种继承-- 寄生组合式继承(6)

news2024/11/27 1:21:59

文章目录

    • 概要
    • 继承的进化史
    • 技术名词解释
    • 寄生组合式继承
    • 案列分析
    • 源代码解析
    • 效果图
      • 调用父类构造函数次数正常
      • 数据也不会混乱
    • 小结

概要

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

继承的进化史

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

在这里插入图片描述

技术名词解释

  • 构造函数:构造函数也称之为构造器(constructor),通常是我们在创建对象时会调用的函数。在其他面向的编程语言里面,构造函数是存在于类中的一个方法。虽然es6 中的class也是解决了旧的JS继承方式,但是无奈考官要提问,只能记住了 :) …
  • 原型:原型就是一个对象,也叫原型对象,不同的人叫法不一样,很容易搞懵逼初学者,原型===原型对象。
  • 原型链:就是实例对象和原型对象之间的链接,每一个对象都有原型,原型本身又是对象,原型又有原型,以此类推形成一个链式结构,称为原型链。
  • prototype :子类构造函数 所指向的原型(实例化的父类)Children.prototype = new Parent(); 这个是手动指向
  • proto:子类实例对象 所指向的原型(实例化的父类) 这个是new 操作符里面的操作

寄生组合式继承

组合式继承 = 原型链继承 + 构造函数继承。
寄生组合式继承 = 寄生功能 + 组合式继承 = 寄生功能 + 原型链继承 + 构造函数继承。

这边回顾一下组合式继承有什么缺点,主要是实例化了父类的次数 = 子类实例化次数 + 1 (子类原型指向了父类的实例)。
其实就目前电脑的配置,这点也无关紧要,实例化一个父类能造成多大的性能损耗呢。
但还是有强迫症换成相处了解决方案,因为父类的上下文已经用构造函数继承了,只要再继承父类的原型链就好了,实现的方案就是将子类的原型指向父类的原型。

案列分析

  • 父类:Parent,要被继承的类,可以理解为人。
  • 子类:Children,要继承父类的类,可以理解为不同的工种,但是还是一个人,所以继承了父类的一些基础属性。
  • 寄生工厂:childrenFactory,将子类的原型prototype指向父类的prototype即可,记得Children.prototype.constructor=Children.
  • 实例:person1 ,person2,实例化的子类

这里是原型链继承,这次继承父类的原型。
父类的数据以及方法要给子类继承,通过了JS的原型链的原理,将子类的prototype,指向了实例化的父类。
Children.prototype = new Parent();
继承是实现了,但是打印对象发现结构不对,少了个构造函数,文章下方也有截图展示对比
Children.prototype.constructor = Children;
只需要将子类的原型指向父类的原型即可。
childrenFactory(Children, Parent);

父类属性:

  1. name:公共属性,每个人都有名字 基础数据类型
  2. age:公共属性,每个人都有年龄 基础数据类型
  3. data:公共属性,个人的一些数据,可以理解为个人的收藏,有人喜欢红酒,有人喜欢首饰,这里的是复合数据类型,需要注意,有时候误操作会影响到其他实例,因为它存放的是一个地址。
  4. sayName:公共方法
  5. sayData:公共方法,用来打印等下误操作的数据问题,打印BUG的地方…
  6. sayAge:父类原型对象上的方法 主要是为了跟构造函数继承对比,构造函数的缺点就是无法使用原型链上的数据...
  7. job:子类的属性
  8. 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>由于要打印原型对象,在浏览器操作比较方便,就用了html文件。</h4>
    <script>
      // 父类
      function Parent(name, age, dataA, dataB) {
        console.warn("Parent 实例化了...");
        // 基本数据类型
        this.name = name;
        this.age = age;
        // 复合数据类型
        this.data = { a: dataA ? dataA : "a", b: dataB ? dataB : "b", c: "c" };

        // 父类内部方法
        this.sayName = function () {
          console.log("我的名字:", this.name);
        };

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

      // 父类原型链方法 (这个跟原型链继承只有半毛钱关系...)
      Parent.prototype.sayAge = function () {
        console.log("我的年龄:", this.age);
      };

      // 子类,不同工种
      function Children(name, age, dataA, dataB, job) {
        // 原型链继承无法通过super 传递给父类,只能通过覆盖的形式了
        Parent.call(this, name, age, dataA, dataB);
        this.job = job;
        this.sayJob = function () {
          console.log("我的工作:", this.job);
        };
      }

      // 这里不使用实例化的父类,不然会调用2次父类的构造函数。
      // Children.prototype = new Parent();
      // 子类已经通过构造函数继承了父类,现在只要继承父类的原型即可。
      // 这边可以寄生式继承的方法,将父类原型绑定到子类即可。
      function childrenFactory(Children, Parent) {
        let prototype = Object.create(Parent.prototype);
        prototype.constructor = Children;
        Children.prototype = prototype;
      }

      childrenFactory(Children, Parent);

      let person1 = new Children(
        "钟先生",
        33,
        "person1A",
        "person1B",
        "程序员"
      );
      // 基本数据类型
      person1.sayName();
      person1.sayAge();
      person1.sayJob();
      // 复合数据类型
      person1.sayData();

      console.log("===person2...");
      let person2 = new Children(
        "刘小姐",
        18,
        "person2A",
        "person2B",
        "清洁阿姨"
      );
      // 基本数据类型
      person2.sayName();
      person2.sayAge();
      person2.sayJob();
      // 复合数据类型
      person2.sayData();

      console.log("===重新打印person1,不用实例化,看看person1会不会被影响...");
      // 基本数据类型
      person1.sayName();
      person1.sayAge();
      person1.sayJob();
      // 复合数据类型
      person1.sayData();
      console.log(
        "===父类构造函数只执行了2次,复合数据类型也不会混乱,很棒..."
      );

    </script>
  </body>
</html>


效果图

这里可以对比本博客所在专栏的组合式继承

调用父类构造函数次数正常

由于Children原型链继承,只继承父类的原型,所以调用父类构造函数的次数=实例化的次数。
在这里插入图片描述

数据也不会混乱

在这里插入图片描述

小结

到这里,传统的JS继承就结束了,总结就2个BUG:

  1. 原型链继承问题。
  2. 复合数据类型混乱问题。

复合数据类型解决方案,只有构造函数继承,因为它是单独开辟一片内存区了。
寄生组合式继承完美解决了上述2个BUG,下一篇将讲解class继承,就是ES6才有的关键字,看看class继承寄生组合式继承有什么区别,还是殊归同途呢。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RNN架构解析——LSTM模型

目录 LSTMLSTM内部结构图 Bi-LSTM实现 优点和缺点 LSTM LSTM内部结构图 Bi-LSTM 实现 优点和缺点

SpringMVC 有趣的文件

文章目录 SpringMVC 文件上传--文件下载-ResponseEntity<T>文件下载-ResponseEntity<T>案例演示代码应用小结完成测试(页面方式) SpringMVC 文件上传基本介绍应用实例需求分析/图解代码实现完成测试( 页面方式) SpringMVC 文件上传–文件下载-ResponseEntity 文件…

13.3 【Linux】主机的细部权限规划:ACL 的使用

13.3.1 什么是 ACL 与如何支持启动 ACL ACL 是 Access Control List 的缩写&#xff0c;主要的目的是在提供传统的 owner,group,others 的read,write,execute 权限之外的细部权限设置。ACL 可以针对单一使用者&#xff0c;单一文件或目录来进行 r,w,x 的权限规范&#xff0c;对…

三层架构与MVC模式

MVC模式 MVC模式是软件工程中常见的一种软件架构模式&#xff0c;该模式把软件系统&#xff08;项目&#xff09;分为了三个基本部分&#xff1a;模型(Model)、视图(View)、控制器(Controller)。 视图(View) 负责界面的显示&#xff0c;以及与用户的交互功能&#xff0c;例如表…

【解析excel】利用easyexcel解析excel

【解析excel】利用easyexcel解析excel POM监听类工具类测试类部分测试结果备注其他 EasyExcel Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存&#xff0c;poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题&…

【代码随想录 | Leetcode | 第十一天】字符串 | 反转字符串 | 反转字符串 II | 替换空格 | 反转字符串中的单词 | 左旋转字符串

前言 欢迎来到小K的Leetcode|代码随想录|专题化专栏&#xff0c;今天将为大家带来字符串~反转字符串 | 反转字符串 II | 替换空格 | 反转字符串中的单词 | 左旋转字符串的分享✨ 目录 前言344. 反转字符串541. 反转字符串 II剑指 Offer 05. 替换空格151. 反转字符串中的单词剑…

Linux:centos7:zabbix4.0(安装,监控》Linux》Windows》网络设备)

环境 centos7&#xff08;zabbix服务器&#xff09;内网ip&#xff1a;192.168.254.11 外网ip&#xff1a;192.168.0.188&#xff08;去网络yum源下载&#xff09; centos7&#xff08;被监控端&#xff09;内网ip&#xff1a;192.168.254.33win10&#xff08;被监控端&…

怎么学习Java安全性和加密相关知识?

学习Java安全性和加密相关知识是非常重要的&#xff0c;特别是在开发涉及敏感数据的应用程序时。以下是学习Java安全性和加密的一些建议&#xff1a; 基础知识&#xff1a; 首先&#xff0c;了解计算机网络安全的基本概念&#xff0c;包括加密、解密、哈希算法、数字签名等。…

图书管理系统--进阶(动态开辟内存 + 保存数据到文件)

文章目录 动态开辟内存优化改进图书管理系统类型改进初始化图书管理系统的函数改进添加图书信息的函数增加销毁图书信息管理系统的函数 保存数据到文件优化保存图书信息管理系统数据到文件读取数据到图书信息管理系统 完整的代码展示 在 C语言实现图书管理系统的所有基本功能详…

当下哪些行业最容易被AI替代?

随着人工智能&#xff08;AI&#xff09;技术的不断发展&#xff0c;越来越多的行业受到AI的冲击。从工业制造到为人服务&#xff0c;在我们许多未察觉的领域&#xff0c;AI正在逐渐取代传统的人类劳动力。那么哪些行业最容易被AI替代呢&#xff1f; 一、制造业和生产线 制造业…

overflow-x:scroll不生效

父元素的宽度一定要设置,不要使用100%, 使用100%可能会导致父跟子元素的宽度一样, 从而无法滑动 父元素: overflow-x:scroll 根据gpt的答案:

Android 6.0 版本中插件化沙盒环境下IllegalArgumentException Unknown package异常

近期从bugly上发现某个渠道包报错 Unknown package异常问题&#xff0c;经过framework层源码分析&#xff0c;发现是插件化api兼容性问题,该渠道包是运行在沙盒环境(233乐园)。 现象 java 报错栈&#xff1a; 其他设备&#xff0c;次数信息&#xff1a;目前发生android 6.0系…

QT【day2】

完善登录框&#xff1a; //main头文件 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include<QDebug> //信息调试类&#xff0c;用于打印输出 #include<QIcon> //图标头文件 #include<QPushButton> //按钮类头文件 #include…

Web_python_template_injection

考察模版Python flask的模版注入&#xff0c;页面没有回显&#xff0c;只有一段字符串&#xff0c;尝试直接利用Python传参 完全没回显 但是如果直接访问的话&#xff0c;就会利用url报错&#xff0c;将结果给执行带出来&#xff0c;那说明我就可以直接利用这个性质进行ssti模版…

SQL注入--题目

联合查询注入&#xff1a; bugku-这是一个神奇的登录框 手工注入&#xff1a; 点吧&#xff0c;输入0’发现还是&#xff1a; 输入0" 发现报错&#xff1a; 确定可以注入&#xff0c;判断字段有多少个 0"order by 1,2,3# 发现&#xff1a; 说明有两列。 输入 0&qu…

赞同高频接广?品牌复投成B站粉丝催更利器

一直以来&#xff0c;电商行业是B站公开的前五大广告主之一。今年618电商节期间B站发布数据称&#xff0c;B站电商类广告收入迎来爆发&#xff0c;同比增长超400%。其中&#xff0c;站内带货视频数量同比增长近8倍&#xff0c;带货直播场次同比增长近7.5倍。 B站作为中长视频为…

只需要5个技巧,就能让你的独立站更吸引客户

人类很简单——我们都更喜欢第一眼看起来令人心情愉悦的的东西。独立站卖家自由度更高&#xff0c;可以添加很多令人惊叹的产品、调整更优惠的价格并设置多种语言选择来吸引访问者购买&#xff0c;但网站的设计仍然是大多数访问者判断独立站品牌的第一要素。根据可靠调研得知&a…

Linux基础IO(二)

Linux基础IO(二) 文章目录 Linux基础IO(二)缓冲区为什么会有缓冲区缓冲区刷新策略系统有缓冲区吗&#xff1f; 文件系统什么是inode 软硬链接软链接硬链接热知识总结 文件的三个时间动静态库什么是动静态库怎么理解动静态库原理使用 制作一个库前置准备自制静态库使用自制的静态…

根据索引值计算item所在行列索引序号

getRowColIndex(itemIndex 0, colCount 3) {//必选参数&#xff1a;itemIndex是当前元素的索引值&#xff0c;从0开始计算&#xff08;如果是从1开始&#xff0c;则需将传入值-1&#xff0c;即itemIndex--&#xff09;//必选参数&#xff1a;colCount是每一行显示多少个元素r…

使用Anaconda创建虚拟环境并添加到Jupyter notebook内核

1.修改虚拟环境的存放位置&#xff08;可选&#xff09; Windows&#xff1a;打开文件C:\Users\DongZhaoCheng(对应到你本人的用户名)\.condarc,添加envs_dirs: [D:\003SoftDevTool\anaconda_env]&#xff08;对应到你自己执行的目录&#xff09;,保存退出 2.进入系统终端创建…