javascript 7种继承-- 原型链继承分析(1)

news2024/12/23 8:17:11

文章目录

    • 概要
    • 继承的进化史
    • 技术名词解释
    • 原型链的作用
    • 原型链继承
    • 案列分析
    • 源代码解析
    • 效果图
    • 预留问题
    • 小结

概要

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

继承的进化史

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

在这里插入图片描述

技术名词解释

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

原型链的作用

当你访问一个对象的属性(数据或者方法),如果该对象没有该属性,并且它还有原型的话,就会去原型对象找,原型对象找不到该数据,就再找原型对象的原型对象,直到世界尽头…(null)

在这里插入图片描述

原型链继承

原型链继承,主要是靠子类的prototype属性,指向父类的实例,通过原型链的方式,实现继承。JS中每个实例都会有原型。
这里为什么不是每个对象都会有原型呢?

 let obj = {};  // 默认都有原型
 console.dir(obj);

 let obj2 = Object.create(null);  // 通过Object.create() 创建无原型对象
 console.dir(obj2);

案列分析

  • 父类:Parent,要被继承的类,可以理解为人。
  • 子类:Children,要继承父类的类,可以理解为不同的工种,但是还是一个人,所以继承了父类的一些基础属性。
  • 实例:person1 ,person2,实例化的子类,一般实例化后数据就分开了,复合数据类型要注意…

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

父类属性:

  1. name:公共属性,每个人都有名字 基础数据类型
  2. age:公共属性,每个人都有年龄 基础数据类型
  3. data:公共属性,个人的一些数据,可以理解为个人的收藏,有人喜欢红酒,有人喜欢首饰,这里的是复合数据类型,需要注意,有时候误操作会影响到其他实例,因为它存放的是一个地址。
  4. sayName:公共方法
  5. sayData:公共方法,用来打印等下误操作的数据问题,打印BUG的地方…
  6. sayAge:父类原型对象上的方法 主要是为了跟构造函数继承对比,构造函数的缺点就是无法使用原型链上的数据...

源代码解析

<!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) {
        // 基本数据类型
        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);
        };
      }

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

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

      // 原型链继承,构造函数的原型,是一个对象,才会在内存在分配空间,所以是需要实例化的。
      // 这边只写了一个子类,如果是多个子类,其实就会实例化多个原型对象,一般数据不会相互影响,除了复合数据类型,这边不进行验证...
      Children.prototype = new Parent();
      // 不加这句结构不完整,可看文章末尾...
      Children.prototype.constructor = Children;

      console.log("===person1...");
      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(
        "===可以看出,基本数据类型不会被影响到,但是复合数据类型出事了..."
      );

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


效果图

这里可以看出来,复合类型数据被污染了
部分同学不知道哪里修改了数据,这边使用构造函数初始化的时候,修改了,可以去看父类的构造函数!
在这里插入图片描述

下图主要是为了跟构造函数继承对比

在这里插入图片描述

预留问题

这里面功能是实现了,但是Children的实例的第一个原型对象是不是少了一个构造函数?
好像少了构造函数这个标识也不受影响。。。
es6 出来的class类,算是比较完整的,这边截图对比一下原型链继承以及class继承。
在这里插入图片描述
所以需要手动添加

Children.prototype.constructor = Children;

在这里插入图片描述

小结

原型链可以实现继承,但是如果子类实例修改了父类的复合数据类型(对象,方法,数组),就影响到了其他实例。
对于JS继承不熟悉的同学,感觉可以先从class继承开始,了解其结构,因为那个是最简单实现,并且最标准的格式了,大概了解了JS继承逻辑、prototype、proto、[[prototype]]、constructor 在实例中的结构再逐步学习对比其他继承,当然如果不去面试的话,直接用class就好了…

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

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

相关文章

10分钟实现任务调度平台搭建

日常项目中&#xff0c;会有很多需要定时执行的任务&#xff0c;而这些任务的变化比较多&#xff0c;可能随时都要调整&#xff0c;那么对调度的灵活性要求比较高。我们传统的Spring Task或者Quartz&#xff0c;可以实现定时任务调度&#xff0c;但是内置在代码里&#xff0c;修…

Matlab Kappa系数和总体精度OA计算

axlsread(D:\homework\精度验证产品.xlsx); Predicteda(:,1); vala(:,2); g0; for i1:size(a,1) %记录验证结果是否与实际值一致if(Predicted(i)val(i))gg1;end end OAg/(size(a,1));% 计算混淆矩阵 confusion_matrix confusionmat(val, Predicted);% 计算总样本数 total_sa…

全方位对比 Postgres 和 MongoDB (2023 版)

本文为「数据库全方位对比系列」第二篇&#xff0c;该系列的首部作品为「全方位对比 Postgres 和 MySQL (2023 版)」 为何对比 Postgres 和 MongoDB 根据 2023 年 Stack Overflow 调研&#xff0c;Postgres 已经成为最受欢迎和渴望的数据库了。 MongoDB 曾连续 4 年 (2017 - …

Qt Core学习日记——第九天QObjectData

本文结合示例代码更易理解&#xff0c;moc_XTest.cpp文件是写好XTest.h、XTest.cpp后由qt编译生成 版本 Qt5.15.2 示例代码 XTest.h #pragma once #include <qobject.h> #include <QFlags> class XTest : public QObject { Q_OBJECT Q_CLASSINFO("au…

【JavaEE初阶】HTTP请求的构造及HTTPS

文章目录 1.HTTP请求的构造1.1 from表单请求构造1.2 ajax构造HTTP请求1.3 Postman的使用 2. HTTPS2.1 什么是HTTPS?2.2 HTTPS中的加密机制(SSL/TLS)2.2.1 HTTP的安全问题2.2.2 对称加密2.2.3 非对称加密2.2.3 中间人问题2.2.5 证书 1.HTTP请求的构造 常见的构造HTTP 请求的方…

数组(超详解)

数组 1.一维数组1.1 一维数组的创建1.2 数组的初始化1.3 一维数组的使用1.4 一维数组在内存中的储存 2. 二维数组2.1 二维数组的创建2.2 二维数组的初始化2.3 二维数组的使用2.4 二维数组在内存中的储存 3.数组越界4.数组作为函数参数4.1 冒泡排序函数错误设计4.2 数组名是什么…

Gnomon水下环境 中

海下的石头 方法一 nParticleShape1.zhong_lie rand(0,6); nParticleShape1.xuan_zhuanrand(<<0,0,0>>,<<5,360,5>>); 缩放原始物体 写错地方了&#xff0c;播放石头一样 海下的石头 方法二 有点问题&#xff0c;使用旧粒子系统 让第一针有粒子 播…

基于SpringBoot+Vue的摄影跟拍预定管理系统设计与实现(源码+lw+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

Idea 开启 lombook 注解插件处理器

Idea 开启 lombook 注解插件处理器 方便编译器识别 勾选 Enable annotation processing

【每日一题】—— C. K-th Not Divisible by n (Codeforces Round 640 (Div. 4))

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;每日一题 &#x1f48c;其他专栏&#xff1a; &#x1f534; 每日反刍 &#x1f7e1; C跬步积累 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0c;缓称…

【雕爷学编程】Arduino动手做(86)---4*4位 WS2812 全彩模块3

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

导轨表和智能电表有哪些区别?

导轨表和智能电表是两种不同的电表类型&#xff0c;它们在功能、性能和应用领域等方面存在一些区别。下面将从多个方面对这两种电表进行比较和分析。 一、定义和功能 导轨表是一种多功能电力仪表&#xff0c;通常用于测量电流、电压、功率、能量等电参数。它采用模块化设计&am…

小黑子—JavaWeb:第三章 HTTP、Tomcat与Servlet

JavaWeb入门3.0 1. Web核心项目2. HTTP2.2 HTTP请求数据格式2.3 HTTP响应数据格式 3. Tomcat3.1 tomact的基本使用3.2 tomact配置3.3 tomact部署项目3.4 web项目结构3.5 创建MavenWeb项目3.6 IDEA集成本地Tomcat3.7 Tomcat的Maven插件 4. Servlet4.1 Servlet执行流程4.2 Servle…

使用jmeter+ant+jenkins+git搭建自动化测试平台

最近正在学习自动化测试&#xff0c;于是随手搭建了一下jmeterantjenkinsgit平台。 接下来&#xff0c;我会按照jdk&#xff0c;jmeter&#xff0c;ant&#xff0c;jenkins,git这个顺序一步一步的搭建起来。 一、jdk。这个就不多说了。我用的是1.8版本的&#xff0c;配环境变…

c++语言风格字符串和QT风格字符串区别

c语言风格字符串和QT风格字符串区别 API实例 第一个是QT风格字符串 第二个是C风格字符串 c语言风格 string a "hello";std::cout<<a<<endl;;char* aa "hello";qDebug()<<aa;qDebug()<<*aa;QT风格 QString str2("hello2&qu…

VarifocalNet An IoU-aware Dense Object Detector 论文学习

1. 解决了什么问题&#xff1f; 密集目标检测器会预测出大量的候选检测框&#xff0c;如何准确地对它们进行排序是取得优异性能的关键。以前的方法通常会在 NMS 时根据类别得分对预测框做排序&#xff0c;但这可能损害模型表现&#xff0c;因为类别得分并不能体现边框定位的准…

畅网n6005 nas主机更新微码

原因 由于畅网n6005小主机上安装了 pve , 在pve中安装了iStore OS &#xff0c;然后用docker安装了alist 用作nas&#xff0c; 平时在外经常要访问。但是这个机器偶尔死机&#xff0c;导致无法脸上网盘&#xff0c;且家里会断网&#xff0c; 因为我家用这个路由器做软路由。做…

k8s核心概念

一、集群架构与组件 1&#xff0c;相关组件 【1】 master node三个组件 k8s的控制节点&#xff0c;对集群进行调度管理&#xff0c;接受集群外用户去集群操作请求master node 组成&#xff08;四个组件&#xff09;&#xff1a;控制面 API Server&#xff1a;通信kube-Sche…

WormGPT – 网络犯罪分子用来犯罪的人工智能工具

WormGPT – 网络犯罪分子用来发起商业电子邮件泄露攻击的生成式人工智能工具 前言 什么是蠕虫GPT&#xff08;WormGPT&#xff09; WormGPT是基于EleutherAI于2021年创建的大型语言模型GPT-J的AI模型。它具有无限的字符支持、聊天记忆保留和代码格式化功能。 如果未部署适当…

文件或文件夹名称中有空格如何批量去除

平时在工作中会经常碰到文件或文件夹里面有特殊符号&#xff0c;那么要如何批量去除文件名中的特殊符号&#xff1f;其实去符号也不是困难的事&#xff0c;可以使用《文件批量改名高手》对文件名进行批量去除特殊符号&#xff0c;操作步骤如下。 先打开《文件批量改名高手》&a…