原型链与继承

article/2025/9/13 0:35:53

目录

原型链

继承

Javascript为什么没有方法签名?

原型链继承

构造函数继承

组合继承

原型式继承

寄生继承

寄生组合继承


原型链

原型链是一种原型对象和实例对象的关系,通过属性__proto__进行联系。

继承

继承是一种允许我们在已有的类的基础上创建新类的机制,它可以使用父类的所有功能,而且可以在这些功能的基础上进行扩展。继承的方式有两种,一种是接口继承,继承方法签名(方法名称和参数类型组成),另一种是实现继承,继承实际方法,javascript没有方法签名,只能支持实现继承(javascript没有原生的继承机制,没有接口继承也没有父类继承,需要原型链来实现继承,但是随着不断更新,es6有extends可以实现继承)。

Javascript为什么没有方法签名?

首先javascript是一种松散类型或动态语言,不必提前声明变量的类型,处理程序时,自动确定类型,而方法签名又是由方法名称和参数类型组成的,原生javascript没有类型检查,传递多少个参数,参数是什么类型,解析器都不会去验证,javascript的参数是由0或者多个值的数组表示,不像其他语言,要事先创建函数签名,后面调用函数也要跟函数签名设置的一样,所以javascript没有方法签名。

function Target(param) {console.log(param)  //输出 hi ,定义函数的参数数量与调用函数的传入的参数数量可以不一样
}Target("hi",'world')

我们继续讲回继承。

继承又分为:原型链继承、构造函数继承、组合继承、寄生组合继承

原型链继承

function Target() {this.params = ["a","b","c"]
}function Follow() {}Follow.prototype = new Target()let follow_first = new Follow()
follow_first.params.push("f")let follow_second = new Follow()
follow_second.params.push("g")console.log(follow_first.params)   // 输出 ["a", "b", "c", "f", "g"]
console.log(follow_second.params)  // 输出 ["a", "b", "c", "f", "g"]

我们使用构造函数Follow的属性prototype指向构造函数Target创建出来的实例对象,然后再用构造函数Follow创建出两个实例对象follow_first、follow_second,由于原型对象是可以被构造函数创建出来实例对象所共享,所以实例对象follow_first、follow_second向自身属性params数组添加元素,其实是在向原型对象的属性params数组添加元素,所以最后它们的属性params数组输出的结果是一样的。

再然后就是关于我在网上看到的:

在javascript的原型链继承方式中,子类在调用父类的构造函数时不能传参数。

但是我自己写代码去尝试:

function Target(name) {this.params = ["a","b","c"]this.name = name
}function Follow() {}Follow.prototype = new Target("Ben")console.log(Follow.prototype)

输出结果:

表明参数是可以传进去构造函数的,于是我就在网上寻找答案,找到一个比较合理的答案:

并不是语法不能实现对构造函数的参数传递,而是这样做不符合面向对象编程的规则,对象才是属性的拥有者,如果在调用构造函数Target提前将name这个属性赋了值,那么后面构造函数Follow创建出来的实例对象都会拥有这个name属性的值,但是这个name属性的值可能并不是实例对象想要的,而是被迫拥有这个属性的值。

原型链继承的优点:

子类可以通过查找原型链,找到父类的属性。

原型链继承的缺点:

构造函数创建出来的实例共用原型指向的对象,操作原型指向的对象的属性可能会引发问题。

在实例对象定义方法,防止跟父类定义的方法重名。

子类在调用父类的构造函数时不能传参数。

构造函数继承

function Target(name) {this.params = ["a","b","c"]this.name = namethis.fun = function () {return this.params}
}Target.prototype.fun_extra = function () {console.log("go")
}function Follow(name) {Target.call(this,name)
}let follow_first = new Follow("Ben")
follow_first.params.push("g")
console.log(follow_first.params)     // 输出 ["a", "b", "c", "g"]
console.log(follow_first.name)       // 输出 Ben
console.log(follow_first.fun)        // 输出 ƒ () {return this.params}
console.log(follow_first.fun())      // 输出 ["a", "b", "c", "g"]
console.log(follow_first.fun_extra)  // 输出 undefined
console.log(follow_first.fun_extra()) //输出 Uncaught TypeError: follow_first.fun_extra //    is not a functionlet follow_second = new Follow("Ken")
follow_second.params.push("f")
console.log(follow_second.params)    // 输出 ["a", "b", "c", "f"]
console.log(follow_second.name)      // 输出 Ken
console.log(follow_second.fun)       // 输出 ƒ () {return this.params}
console.log(follow_second.fun())     // 输出 ["a", "b", "c", "f"]
console.log(follow_second.fun_extra)  // 输出  undefined
console.log(follow_second.fun_extra())  // 输出 prototype1.js:33 Uncaught TypeError: // follow_second.fun_extra is not a function

构造函数继承解决了子类在调用父类的构造函数时不能传参数与多个实例对象共同操作原型指向的对象的属性的问题,同时也带来父类的原型定义方法对于子类是不可用,子类的实例只能使用父类this绑定的属性的问题。

构造函数继承的优点:

解决了子类在调用父类的构造函数时不能传参数

避免了多个实例对象共同操作原型指向的对象的属性可能会引起问题

构造函数继承的缺点:

父类的原型定义方法对于子类是不可用,子类的实例只能使用父类this绑定的属性

在构造函数定义的方法不能对其进行覆盖

组合继承

function Target(name) {this.params = ["a","b","c"]this.name = name
}Target.prototype.fun = function () {return this.params
}function Follow(name) {Target.call(this,name)
}Follow.prototype = new Target()
Follow.prototype.constructor = Followlet follow_first = new Follow("Ben")
follow_first.params.push("g")
console.log(follow_first.params)     //输出 ["a", "b", "c", "g"]
console.log(follow_first.fun())      //输出 ["a", "b", "c", "g"]let follow_second = new Follow("Ken")
follow_second.params.push("f")
console.log(follow_second.params)   //输出 ["a", "b", "c", "f"]
console.log(follow_second.fun())    //输出 ["a", "b", "c", "f"]

组合继承的优点:

解决了原型链继承的实例对象共享原型对象的属性,导致实例对象的属性隔离性差。

解决了构造函数继承父类的原型定义方法对于子类是不可用的问题。

组合继承的缺点:

父类的构造函数被调用了两次,一次是call函数调用,一次是new关键字调用,导致原型对象与实例对象拥有相同的属性。

原型式继承

function Target(object) {function Follow() {}Follow.prototype = objectreturn new Follow()
}

原型式继承将原型链继承进行封装,还不需要自己去创建新的构造函数,减少代码量。但是还是会有原型链继承的缺点。

寄生继承

function Target(object) {function Follow() {}Follow.prototype = objectreturn new Follow()
}function createTarget(originObject) {let newObject = Target(originObject)newObject.method = function () {console.log("hello")}return newObject
}

寄生继承同样也是一个封装的过程,在原型继承的基础上,给新创建的实例对象增加属性或方法,不过这些属性都是私有属性与方法都是私有,并不能共享。

寄生组合继承

function create(object) {function A() {}A.prototype = objectreturn new A()
}function Target(name) {this.params = ["a","b"]this.name = name
}Target.prototype.fun = function () {return this.params
}function Follow(name) {Target.call(this,name)
}function inheritPrototype(follow,target) {let prototype = create(target.prototype)prototype.constructor = followfollow.prototype = prototype
}
inheritPrototype(Follow,Target)let follow_first = new Follow("Ben")
console.log(follow_first.name)   //输出 Ben

关系图:

寄生组合继承减少调用父类构造函数的次数,用空对象替换掉父类构造函数创建出来的实例对象,使得子类的属性prototype指向这个空对象,避免原型对象与实例对象拥有相同的属性,同时子类创建出来的实例对象可以对父类的方法进行覆盖。寄生组合继承拥有原型链继承和构造函数继承的优点。

 还有一个class继承,后面我再来进行介绍。


http://chatgpt.dhexx.cn/article/Fl2BNGBB.shtml

相关文章

JS原型链和继承

JS原型链和继承 认识对象的原型 [[Get]]:JS的存取描述符——get方法,在获取对象属性时会自动调用 JavaScript当中每个对象都有一个特殊的内置属性[[prototype]],这个特殊的属性指向另外一个对象 [[prototype]]指向的对象: 当我…

JS原型链继承

再讲述JS原型链继承之前,我希望大家能够先理解 《函数,函数原型和函数实例之间的关系》,这样有助于大家理解JS原型链继承的原理,下面先看一张图吧,咱们看图说话: 如果大家看完了 《函数,函数原型和函数实…

原型链和继承的六种实现方式

一省:HTML 12. img标签的alt和title有什么不同? alt: 当图片加载不出来的时候,就会在图片未显示的地方出现一段 alt 设置的属性内容。浏览器的搜索引擎可以通过 alt 属性的文字描述来获取图片。 title: title是鼠…

原型,原型链,原型的继承

原型的作用? 1.节省内存空间 2.实现数据共享(继承) 什么是原型? 任何一个函数都有propotype属性,它本身是一个对象,我们称之为原型 构造函数,实例化对象与原型之间的关系? 1.任何一个函数都有prototype属性,它本身是一个对象,我们称之为原型 2.构造函数也是函数,也都…

JS原型、原型链和7种继承方法【白话文讲解】

前言 在学习JS原型、原型链和继承之前,我们必须先弄懂三个W,也就是我们常说的“学习三问” 学习三问: 1.它是什么?(What) 2. 为什么用它?(Why) 3. 什么时候用它&#xff…

原型链与常用继承方法

原型链:当访问一个对象的属性时,如果该对象内部不存在这个属性,就会去该对象的__proto__ 上(也就是它构造函数的prototype)查找 。该构造函数的prototype上也有一个自己的__proto__ 属性,然后继续向上查找,…

如何用原型链的方式实现一个 JS 继承?

大家好,我是前端西瓜哥。今天讲一道经典的原型链面试题。 原型链是什么? JavaScript 中,每当创建一个对象,都会给这个对象提供一个内置对象 [[Prototype]] 。这个对象就是原型对象,[[Prototype]] 的层层嵌套就形成了…

JS学习笔记 原型链和利用原型实现继承

原型链 原型链是一种关系,实例对象和原型对象之间的关系,关系是通过原型(__proto__)来联系的 实例对象中有__proto__,是对象,叫原型,不是标准的属性,浏览器使用,并且有的游览器不支持构造函数中有prototype属性,也是对象,叫原型 注意 原型中的方法是可…

Arduino基本知识(marlin固件配置)

初识arduino,根据mega2560(某宝可以买到)官网的100个管脚具体控制一句传输进行操作。 https://www.arduino.cc/en/Hacking/PinMapping2560 其管脚图如上所示。 首先在官网下载arduino的配套软件 https://www.arduino.cc/ 对于编程&#xf…

3D打印机硬件驱动-马林固件最新版本2.0.X中文注释(3)marlin 2.0.9.2 截至发稿时间2021年12月16日

/** * Marlin 3D Printer Firmware 头描述详见其他两个文件头描述 * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * Based on Sprinter and grbl. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm * * This program is…

Marlin固件配置

文档来源自http://www.geek-workshop.com/thread-33314-1-1.html 1、基本配置基本配置是可选的,主要是给你的固件起个名字,如果你的配置很牛,让大家知道你是谁。据说这个在启动的时候会显示在显示屏中,应为我没有显示屏,所以无法验证。这个修改也很简单,通过搜索找到“S…

MKS MONSTER8 V1.0使用说明书(基于Marlin 2.0.X固件配置Voron 2.4)

广州谦辉信息科技有限公司 (基于Marlin 2.0.x 固件配置 Voron 2.4) 创客基地QQ群:489095605 232237692 邮箱:Huangkaidamakerbase.com.cn 主板购买链接:https://item.taobao.com/item.htm?spma1z10.5-c-s.w4002-23356668283.43.7eec55caLT…

ESP32烧录Marlin固件

安装platformIO 这点很简单,保证你拥有一个能够成功连接外网的环境即可。内网可能不太稳定有可能安装失败。 克隆代码 我这里采用的是fyset_e4的代码,这个代码开源在了https://github.com/FYSETC/FYSETC-E4,作者已经针对marlin固件做了一些配置。 更改…

i3型3D打印机制作详解——Marlin固件中文介绍

关注微信公众号:嵌入式基地 后台回复:3d打印机 获取资料 硬件框架搭建介绍 https://blog.csdn.net/qq_39020934/article/details/80380250 Marlin固件中文介绍 https://download.csdn.net/download/qq_39020934/10401251 …

3D打印机Marlin固件双Z轴设置

3D打印机Marlin固件双Z轴设置 在3D打印机Marlin固件的最新版本2.1.1中,设置双Z轴和老版本有一些改动。记录一下如何在最新版本的Marlin固件中设置双Z轴。 以MKS GEN_L V2.1的主板为例,硬件连接还是和原来一样,第二个Z轴的电动机连接到空闲的…

Marlin 固件配置手动退换料

换料的步骤首先把喷头加热,软化喷嘴里残余的线材,然后反转挤出机,把线材抽出来。最后装入新线材,并挤出余留在喷头里的材料。整个过程用一个命令 M600 就能完成。默认情况下 Marlin 固件并没有开启这个功能,但是可以修…

MKS_SGEN_L V1.0 marlin 固件编译

1.下载 Visual Studio Code 打开Visual Studio Code 安装插件 在应用商店搜索下载安装如下图: 安装完这些还是不行的 还要另外安装python 3.8.8 其他版本python 不行右下角会报错,提示安装python 3.8 python 3.8.8 百度网盘下载链接:https://pan.bai…

3D打印机硬件驱动-马林固件最新版本2.0.X中文注释(1)marlin 2.0.9.2 截至发稿时间2021年12月16日

马林固件最新版本翻译注释 /* Marlin Firmware 马林固件 (c) 2011-2020 MarlinFirmware Portions of Marlin are (c) by their respective authors. 马林部分程序来源于世界各地的开发者 All code complies with GPLv2 and/or GPLv3 所有源码依靠GPLv2 和 GPLv3架构编写…

Marlin固件学习总结(一)

接触过3D打印也有一段时间了,一直没有将学到的知识以文本的形式记录下来。现在也没有太多时间继续玩这个了,因此想慢慢把之前所接触到所学到的知识通过文本的形式记录一下,也分享给那些感兴趣的人。 既然是开篇我们先了解一下marlin固件的结构…

Marlin固件之二:源代码详解与移植

由于需要进行固件定制化,Marlin固件太过于强大和紧凑,我对这个固件进行了裁剪,只剩下主枝干,实现功能的定制和裁剪。以下的代码详解是基于我已经移植在stm32上面的一个程序进行的。