• 【JavaScript 进阶教程】非 extends 的组合继承


    ??欢迎继续来到 JavaScript 进阶教学!

    继承也是面向对象的特性之一,但是在 ES6 版本之前是没有 extends 去实现继承的,我们只能通过构造函数原型对象来实现继承,其中分别为构造函数来继承属性,原型对象来继承方法,这种继承模式被称为组合继承



    文章目录:

    一:call() 的作用与使用?

    1.1 使用 call() 来调用函数?

    1.2?使用 call() 来改变 this 的指向?

    ?二:利用构造函数继承父属性

    2.1 实现过程?

    2.1 实现过程分析

    三:利用原型对象继承父方法?

    ?3.1 继承父方法的错误演示

    问题原因?

    ?3.2?继承父方法的正确做法

    ??3.2?继承父方法的注意事项


    一:call() 的作用与使用

    在开始讲解组合继承前我们先来了解一下 call() 方法,call() 方法可以改变 this 的指向,也可以调用函数等等,最主要的还是其改变指向的作用

    语法格式

    call( 目标this指向,参数1,参数2…)


    1.1 使用 call() 来调用函数

    call() 可以拿来直接用来调用函数

         
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6


    1.2使用 call() 来改变 this 的指向

    call() 的第一个参数为你要改变的 this 的指向,这里的 this 指的是 call 的调用者,此处函数调用不指定的话即指向 window,指定让其指向新创建的对象 obj,只需要让其第一个参数为 obj 对象即可,所以结果应该是第一个为 window,第二个为 obj 对象

         
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11


    二:利用构造函数继承父属性

    我们已经知道组合继承是由构造函数和原型对象一起来实现的,其中构造函数实现的是属性的继承,原型对象实现的是方法的继承,这版块就走进利用父构造函数完成属性的继承

    2.1 实现过程

    其实现非常容易,只需要在子构造函数中,使用 call 调用父构造函数(将其当做普通函数调用),其中在 call 方法中更改父构造函数中的 this 指向,由于 call 方法是在子构造函数中调用的,所以此处当做参数的 this 代表父构造函数中的 this 指向子构造函数的实例化对象,并传参进去,所以相当于给子构造函数的实例化对象添加了属性并赋值

         
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15


    2.1 实现过程分析

    • 首先在子构造函数中使用 call 调用了父构造函数,并传参给 call 的参数,其中第一个参数为 this 指向的改变,其余为带入的属性值参数
    • 我们知道构造函数中的 this 指向其实例化对象,所以本身父构造函数的 this 应该指向父构造函数的实例化对象,而此处 call 方法调用在子构造函数中,所以参数的指向更改为指向子构造函数的实例化对象
    • 此处子构造函数的实例化对象就是 son1,所以父构造函数中的 this 指向的均是 son1,
    • 所以就给 son1 添加并赋值了 uname,uage 等等属性


    三:利用原型对象继承父方法

    组合继承的最后一版块,利用原型对象来继承方法,此处我们说明的是存放在构造函数的原型对象里的公共方法的继承

    3.1 继承父方法的错误演示

    错误的继承就是直接将父亲的原型对象赋值给子的原型对象,这样确实也可行,但是如果给子原型对象添加子类特有的方法,那父原型对象也会加上这个方法

         
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    我们可以发现父子的原型对象中确实都有了这个方法,证明确实这个办法是行得通的

    但是其也有问题存在,当我们想给子原型对象单独添加其特有的方法时,就会出问题

    • 上述问题给子原型对象添加特有方法的错误示例:

       
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22

    我们发现,我们确实给儿子添加上了儿子特有的方法,但是,父亲的原型对象内也加上了这个方法,这并不满足我们的预期,原因分析如下

    • 问题原因

    问题就在于我们的原型对象也是对象,对象是引用数据类型,引用数据类型的对象本质是在堆内存存放,是不能直接访问的,其访问是通过栈内存上的引用地址来找到去访问,而我们此处采用的等号赋值的方式,实际上是将其在栈内存上的引用地址拷贝过去了,二者指向了同一块内存空间,所以更改子原型对象,父原型对象也改变了


    3.2继承父方法的正确做法

    正确的做法是让其子原型对象对象等于父实例化对象Son.prototype=new Father(),其实我感觉有种高内聚低耦合的韵味,减少了直接联系从而解决问题

         
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    问题得以解决,子原型对象有了自己特有的方法,并且也继承了父亲原型对象中的方法


    3.2继承父方法的注意事项

    我们以 Son.prototype=new Father() 这种方法继承,看似已经天衣无缝,其实我们早就说过,采用等号赋值的方法会造成原型对象被覆盖,里面的构造函数 constructor 会被覆盖掉,需要我们手动返回,所以七千万要记得手动返回 constructor

         
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    感谢阅读,下篇更精彩!!!

    先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

  • 相关阅读:
    【5GC】5G PDU会话以及会话类型
    【Day20】集合
    【uni-app】路由
    12412 - A Typical Homework (a.k.a Shi Xiong Bang Bang Mang) (UVA)
    30人小公司,5分钟自助上线,快速搭建私有云盘?
    Python实现文字识别OCR
    稳压电源: 电路图及类型
    如何搭建mysql的主从关系
    Win11如何删除升级包?Win11删除升级包的方法
    《利息理论》指导 TCP 拥塞控制
  • 原文地址:https://blog.csdn.net/m0_67401545/article/details/126080575