javascript 7种继承-- 原型式继承分析(4)

news2024/12/21 19:54:30

文章目录

    • 概要
    • 继承的进化史
    • 技术名词解释
    • 原型式继承
        • 原型式继承1
        • 原型式继承2
        • 对比图
    • 原型链继承 vs 原型式继承
    • 案列分析
    • 源代码解析
    • 效果图
    • 小结
        • 优点
        • 缺点

概要

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

继承的进化史

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

在这里插入图片描述

技术名词解释

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

原型式继承

道格拉斯·克罗克福德在一篇文章中介绍了一种实现继承的方法,这种方法并没有使用严格意义上的构造函数。它的想法是借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。

原型式继承1

let obj = {
	name: "Penk是个码农",
	data: {
	  a: 1,
	  b: 2,
	  c: 3,
	},
	sayData: function () {
	  console.log(this.data);
	},
};
function createObj(obj) {
	function Fun() {}
	Fun.prototype = obj;
	return new Fun();
}

let parent = createObj(obj);
console.log(parent);

原型式继承2

es5新增了一个类似功能的函数,Object.create();

let obj = {
	name: "Penk是个码农",
	data: {
	  a: 1,
	  b: 2,
	  c: 3,
	},
	sayData: function () {
	  console.log(this.data);
	},
};

let parent = Object(obj);
console.log(parent);

对比图

如下,可见基本一样了…
在这里插入图片描述

原型链继承 vs 原型式继承

之前讲的其他文章,原型链继承,构造函数继承,组合式继承都是以构造函数为基础的继承,原型式继承感觉就是通过对象,所以在这里可能会难以理解,但是也确实是实现了继承,没办法,开发用不上,但是考官可不理你... : <

  • 原型链继承,是将子类的prototype指向父类实例,父类是子类的原型对象,从而实现原型链继承。
  • 原型式继承,返回一个空的构造函数所创建的实例,并该构造函数的prototype指向需要继承的对象,说白了就是直接浅拷贝copy一个新的对象给你用,可以参考原型式继承的一句话代码:let parent2 = Object.create(obj);

案列分析

之前的案例都是用父子类,这边依旧用它,不能因为换了技术方案就要换个场景。

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

源代码解析

原型式继承是通过对象浅拷贝,再通过.操作符添加属性已到达继承跟重写的功能。

<!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>
    <script>
      let obj = {
        name: "未初始化的人",
        data: {
          a: 1,
          b: 2,
          c: 3,
        },
        sayData: function () {
          console.log(this.data);
        },
        setDataA: function () {
          this.data.a = 666;
        },
      };

      // 第一种方式,函数传参返回一个实例
      // 该实例对应的构造函数的原型指向了传参
      function createObj(obj) {
        function Fun() {
          // ... 这里不可以有方法以及属性,不然会覆盖Fun的原型对象上的方法以及属性
        }
        // 父类的公共方法以及属性需要放在这里,会被 "Fun.prototype = obj;" 覆盖...
        // ... Fun.prototype.name = "";
        Fun.prototype = obj;
        // 放在这里也不可以,会覆盖传进来的参数obj
        // ... Fun.prototype.name = 111;
        // ... Fun.prototype.sayName = function () {
        // ...   console.log(this.name);
        // ... };
        return new Fun();
      }

      // 就当成一个父类吧
      let parent = createObj(obj);
      console.log(parent);

      // 所以说,原型式继承,只能继承传进来的参数obj
      // 第二种方式创建obj,使用object.create()
      let parent2 = Object.create(obj);
      console.log(parent2);

      console.log(
        "=====通过上面的对比,可以得知,Object.create(),可以实现原型式继承..."
      );

      console.log("=====================");
      console.log("=====================");
      console.log("接下来要展示原型式继承的BUG...");

      // 就当成一个子类
      let children = Object.create(parent);
      children.job = "未找到工作";
      children.sayJob = function () {
        console.log(`${this.name} 的工作是${this.job}...`);
      };

      // 实例化2个子类对象
      let person1 = Object.create(children);
      let person2 = Object.create(children);

      // 真的不知道怎么初始化,没找到相关资料...
      // 这边就随便来了,有好建议欢迎交流.
      person1.name = "钟先生";
      person1.job = "程序员";

      console.log(person1);
      console.log(person2);

      person1.sayJob();
      person2.sayJob();

      console.log("大概就是这样,一层套一层,还不能传参...");
      console.log("=====================");
      console.log("=====================");
      console.warn("====这里如果使用了复合数据类型的话,也会出现数据混乱...");

      // 初始化
      person1.name = "钟先生";
      person1.job = "程序员";

      person2.name = "刘小姐";
      person2.job = "清洁阿姨";

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

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

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

效果图

实例化了person1跟person2 两个实例对象,并且都初始化了,第一次打印数据,相同没问题,第二次打印前,person1修改了原型上的复合数据类型中的变量a=>person1.__proto__.data.a的值,这里是引用类型数据,所以混乱了。

在这里插入图片描述

小结

优点

无。

缺点

  • 无法传参
  • 如果传参的对象有复合数据类型,若是修改,会造成数据混乱。
  • 对父类功能进行重写只能通过.操作符,下一次将用升级版:寄生式继承

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

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

相关文章

【前端学java】JAVA中的packge与import

packge与import示例 Java中&#xff0c;使用package关键字来声明一个类所属的包&#xff1a; package myapp;public class MyClass {// 类的实现... }上述代码中&#xff0c;MyClass类被声明为属于myapp的包。在其他的代码中使用该类时&#xff0c;需要使用完整的包名来引用它…

学习DT材质基础

Lambert材质和常用颜色属性 Maya材质的发光属性 Maya材质的光线跟踪属性 看不见阴影是因为背景用错材质了 MAYA矢量渲染 各向异性材料&#xff08;看高光&#xff09; 渐变材质 开启光线跟踪 表面着色器材质

微服务——Docker

docker与虚拟机的区别 首先要知道三个层次 硬件层:计算机硬件 内核层:与硬件交互&#xff0c;提供操作硬件的指令 应用层: 系统应用封装内核指令为函数&#xff0c;便于程序员调用。用户程序基于系统函数库实现功能。 docker在打包的时候直接把应用层的函数库也进行打包&a…

【GeoDa实用技巧100例】015:Geoda构建箱线图

文章目录 一、箱线图介绍二、Geoda制作箱形图三、箱形图与箱形地图的链接一、箱线图介绍 箱形图,也称箱线图(Box and Whisker Diagram)、箱图、盒须图、盒式图和盒形图等,是一种用作显示一组数据分散情况资料的统计图。因形状如箱子而得名。箱形图是由美国著名统计学家图基在…

vue3-组件中的变化

1. 路由 1. 安装指令&#xff1a;npm i vue-routernext 2. 创建路由&#xff1a;createRouter2. 异步组件&#xff08;defineAsyncComponent&#xff09; defineAsyncComponent 是用于定义异步组件的函数。defineAsyncComponent 接受一个工厂函数作为参数&#xff0c;这个工厂…

opencv-22 图像几何变换01-缩放-cv2.resize()(图像增强,图像变形,图像拼接)

什么是几何变换&#xff1f; 几何变换是计算机图形学中的一种图像处理技术&#xff0c;用于对图像进行空间上的变换&#xff0c;而不改变图像的内容。这些变换可以通过对图像中的像素位置进行调整来实现。 常见的几何变换包括&#xff1a; 平移&#xff08;Translation&#x…

力扣热门100题之无重复字符的连续子串【中等】

题目描述 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”&#xff0c;所以其长度为 3。 示例 2: 输入: s “bbbbb” 输出: 1 解释: 因为无重复字符的最长子…

Java8实战-总结6

Java8实战-总结6 通过行为参数化传递代码对付啰嗦匿名类第五次尝试&#xff1a;使用匿名类第六次尝试&#xff1a;使用Lambda表达式第七次尝试&#xff1a;将List类型抽象化 真实的例子用Comparator来排序 通过行为参数化传递代码 对付啰嗦 人们不愿意用那些很麻烦的功能或概…

个微API,微信机器人开发

简要描述&#xff1a; 退出群聊 请求URL&#xff1a; http://域名地址/quitChatRoom 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必选类型说明wI…

Redis实战案例24-关注推送

1. Feed流实现方案 拉模式主要缺点&#xff0c;延迟问题&#xff0c;极端情况某个用户关注了成千上万的up主&#xff0c;每位up主又发布了十几条博客&#xff0c;此时拉模式的延迟就会很高&#xff1b; 推模式缺点也很明显&#xff0c;内存消耗太大&#xff0c;假设up主是千万级…

【idea工具】idea工具,build的时候提示:程序包 com.xxx.xx不存在的错误

idea工具&#xff0c;build的时候提示:程序包 com.xxx.xx不存在的错误&#xff0c;如下图&#xff0c;折腾了好一会&#xff0c; 做了如下操作还是不行&#xff0c;idea工具编译的时候&#xff0c;还是提示 程序包不存在。 a. idea中&#xff0c;重新导入项目&#xff0c;也还…

基于DNN深度学习网络的OFDM+QPSK信号检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ............................................................................. Transmitt…

区块链实验室(11) - PBFT耗时与流量特征

以前面仿真程序为例&#xff0c;分析PBFT的耗时与流量特征。实验如下&#xff0c;100个节点构成1个无标度网络&#xff0c;节点最小度为5&#xff0c;最大度为38. 从每个节点发起1次交易共识。统计每次交易的耗时以及流量。本文所述的流量见前述仿真程序的说明:区块链实验室(3)…

页面设计—FlexContainer弹性容器组件详解

一、组件介绍 Flex 是 Flexible Box 的缩写&#xff0c;意为"弹性布局"&#xff0c;用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为 Flex 布局&#xff0c;可以与栅格布局结合使用。 二、样式介绍 三、如何使用 &#xff08;1&#xff09;找到FlexCo…

实用!SD人物表情提示词合辑;秒变大神的Python速查表;开源LLM微调训练指南;LLM开发必修课 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 太实用了&#xff01;Stable Diffusion 的24个表情提示词 Pensive 沉思 Smiling 微笑 Disgusted 厌恶 Laughing 大笑 Shocked 震惊 Fr…

【数据分析专栏之Python篇】全网最细Anaconda安装与配置

文章目录 [toc] 前言一、 Anaconda是什么1.1 简介1.2 特点1.3 Anaconda、conda、pip、virtualenv的区别 二、为什么使用Anaconda三、安装步骤3.1 下载安装3.2 配置conda源 四、结语五、附录六、参考 前言 大家好&#xff01;本篇给大家介绍 Anaconda 安装及配置。 一、 Anaco…

【分享】揭秘BlueWillow::AI绘画工具的平替新选择

哈喽&#xff0c;木易巷上线啦&#xff01; 今天我要给大家介绍一个全新的AI绘画工具——BlueWillow。如果你正在寻找一款能够替代Midjourney的工具&#xff0c;那么BlueWillow绝对值得一试&#xff01; 官网链接和邀请链接都在最后哦&#xff01; 首先&#xff0c;BlueWillo…

< 今日小技巧:Axios封装,接口请求增加防抖功能 >

文章目录 &#x1f449; 前言&#x1f449; 一、核心代码 &#xff1a; 防抖函数&#x1f449; 二、Axios封装中的配置&#x1f449; 三、实现原理&#x1f449; 结论&#x1f449; 补充优化&#xff1a; 解决多个接口请求&#xff0c;拦截掉了需要的请求> 防抖函数> 引用…

c 学习笔记(自用)---GCC编译器

1.GCC编译器的使用 1&#xff09; 一个c文件预处理和编译的过程 可以用以上命令去逐步调试下&#xff0c;看看预处理的过程 2&#xff09;命令举例与解释 #源文件较少的情况下 gcc -o test main.c sub.c #分别将 main.c 和sub.c文件进行预处理、编译、汇编&#xff0c; #…

push_back 和 emplace_back 的区别

文章目录 1、vector::push_back1.1 void push_back(T&& x) ; (C11)参数返回值类型大小 和 容量移动左值用户自定义类型使用 push_back 1.2 void push_back(const T &x);参数返回值类型 1.3 如果 vector 的 size 超过当前capacity&#xff0c;push_back 会使迭代器、…