JavaScript面向对象:类的几种继承方式

2023-11-20


前端小白记录学习笔记,不做他用。

类与实例

类的声明

·

  1. 用构造函数模拟类(传统写法)

function Person1(name){
this.name=name;
}

  1. 用class声明(ES6写法)

class Person2{
construtor(name){
this.name=name;
}
}

控制台输出:
自制截图,哼!

生成实例

类的实例化很简单,直接new就可以。
自制截图,哼!

类与继承

如何实现继承

继承的本质就是原型链。

继承的几种方式

  1. 借助构造函数
function Parent1(){
	this.name="parent莉莉";
}
function Child1(){
	Parent1.call(this);//改变this的指向,非常重要。用apply或者call都行
	this.type="child莉莉";
}
console.log(new Child1);

在上面的代码中,最重要的是在子类的构造函数中写了 Parent1.call(this);,这样是为了让Parent1的构造函数在Child1的构造函数中执行。this的指向发生改变,Parent的实例——>改为指向Child1的实例,导致Parent1的实例属性挂到Child1的实例上,这样就实现了继承。
控制台打印结果:
自制截图,哼!
上面截图表明:Child1先有Parent1实例的属性,再有Child1实例的属性。
分析
这种方式虽然改变了this的指向,但是Child1无法继承Parent1的原型。也就是说,如果我给Parent1的原型添加一个方法:

Parent1.prototype.say=function(){...};

这个方法是无法被Child1继承的。

  1. 通过原型链实现继承
function Parent(){
	this.name="parent属性";
}
function Child(){
	this.type="child属性";
}
Child.prototype = new Parent();//原型链
console.log(new Child);

上方代码最重要的是Child.prototype = new Parent();。每个函数都有prototype属性,构造函数也有这个属性,这个属性是一个对象。我们用这行代码Child.prototype = new Parent();把Parent的实例赋给Child的prototype,从而实现继承。Child的实例,Child构造函数,Parent的实例构成一个三角关系,从而,new Child.__proto__===new Parent() =true;
分析
这种继承方式,Child可以继承Parent原型,但是有个缺点:如果修改了child1实例的name属性,那么child2实例的name属性值也会发生变化,显然这样不太好。
在实际业务中,两个子模块对象应该隔离开才对。如果修改一个对象,另一个对象也发生改变,这样对业务设计不太好。造成这种缺点的原因是child1和child2共用原型,也就是说child1.__proto__===child2.__proto__的结果为true。

  1. 组合的方式:构造函数+原型链
//组合方式实现继承:构造函数+原型链
function Parent2(){
	this.name="parent属性";
	this.arr=['1','2','3'];
}
function Child2(){
	Parent2.call(this);//执行parent方法
	this.type="child属性";
}
Child2.prototype=new Parent2();//第二次执行parent方法
var child = new Child2();

这种组合的方式能够解决以上两种继承方式的缺点:既能继承原型的属性内容,也不会造成原型属性的修改。

  1. 原型式继承
    不用严格意义上的构造函数,借助原型可以根据已有的对象创建新对象,而且不必因此创建自定义类型。
function Object(obj){
	function Func(){};
	Func.prototype = o;
	return new Func();
}

从本质上讲,Object对传入其中的对象做了一次浅复制。举个例子:

var person={
	name:'Lily',
	friends:['ann','julia']
}
var onePerson=Object(person);
onePerson.name='jun';
onePerson.friends.push('jessica');

var anotherPerson = Object(person);
anotherPerson.name='ton';
anotherPerson.friends.push('jennie');

console.log(person.friends);
//['ann','julia','jessica','jennie']

在这个例子中,相当于创建了person的两个副本。

  1. 寄生式继承
    寄生式继承是与原型式继承紧密相关的一种思路,它创造一个仅用于封装继承过程的函数,在函数内部增强对象,最后再返回对象。
function CreatePerson(origin){
	var clone = Object(origin);
	clone.say=function(){
		console.log('hello');
	};
	return clone;
}

缺点:使用寄生式继承来为对象添加函数,会因为函数不可复用而降低效率,这个与构造函数继承类似。

  1. 寄生组合式继承
    基本思想:通过借用构造函数来继承属性,通过原型链的混成方法来继承方法,不必为了指定子类型的原型而调用超类型的构造函数,只需要超类型的一个副本。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类的原型。
function inherit(sub,super){
	var obj = Object(super);//创建对象
	obj.constructor=sub;//增强对象
	sub.prototype=obj;//指定对象
}

因此,前面的例子可以改成以下形式:

function super(name){
	this.name=name;
	this.colors=['red','green'];
}
super.prototype.sayName=function(){
	console.log(this.name)
}
//继承属性
function sub(name,age){
	super.call(this,name);
	this.age=age;
}
//继承方法
inherit(sub,super);
sub.prototype.sayAge=function(){
	console.log(this.age);
}

优点:只调用一次super构造函数,因此避免了在sub.prototype上创建不必要的、多余的属性,与此同时,原型链还能保持不变,还能正常使用instanceof和isPrototypeOf(),因此,寄生组合式继承被认为是引用类型最理想的继承范式。

以上六种方式是ES5继承。ES5的继承可以用下图概括

转载自网络,侵权联系删除
ES6继承主要注意class的继承。class之间通过extends关键字实现继承,这比修改原型链实现继承要好。

class ColorPoint extends Point{
	constructor(x,y,color){
		super(x,y);
		this.color=color;
	}
	toString(){
		return this.color+' '+super.toString();
	}
}

注意:子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。因此,只有调用super之后,才可以使用this关键字。
一条继承语句同时存在两条继承链:一条继承属性,一条继承方法。

class A extends B{};
A.__proto__=B;//继承属性
A.prototype.__proto__=B.prototype;//继承方法

ES6的继承可以用下图概括:
转载自网络,侵权联系删除

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaScript面向对象:类的几种继承方式 的相关文章

随机推荐

  • 3D点云处理:Opencv Pcl实现深度图转点云(附源码)

    文章目录 0 测试效果 1 代码实现 文章目录 3D视觉个人学习目录 0 测试效果 处理结果 1 代码实现 文章中提供的深度图像 深度图像一般以 tiff和 png保存 可以通过Opencv中的 c v i m r
  • docker入门---最全笔记

    前言 小编我将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识 有兴趣的小伙伴可以关注一下 也许一个人独行 可以走的很快 但是一群人结伴而行 才能走的更远 让我们在成长的道路上互相学习 让我们共同进步 欢迎关注 目录 前言 一 D
  • FFMPEG进阶系列02-ffmpeg命令详解3

    文章目录 ffmpeg 的封装转换 ffmpeg的编转码 ffmpeg 的基本编转码原理 过滤器链 filter chain 码率 帧率和文件大小 帧率 帧率和文件大小 调整视频分辨率 调整视频分辨率 scale filter调整分辨率 裁
  • Go Web编程实战(10)----模板引擎库text/template包的使用

    目录 前言 模板引擎 定义模板文件 解析模板文件 渲染模板 实战使用模板 创建 tmpl文件 创建文件用于解析与渲染模板 前言 在Go语言中 模板引擎库text template包主要用于处理任意格式的文本内容 同时还提供了html tem
  • IP网址可访问,域名网址无法访问

    可以通过修改DNS排查问题 一 修改DNS的好处 适当提高上网速度 更换DNS可以访问某些因为域名解析存在问题而不能访问的网站 可以屏蔽运营商的广告 还可以帮助您避免被钓鱼的危险 二 修改DNS带来的副作用 无法访问页面或者访问的页面不是你
  • Ubuntu 20.04 配置深度学习开发环境

    目录 写在前面 Dependency 1 安装Anaconda 1 1 下载安装包 1 2 进入安装文件夹 执行安装脚本 1 3 环境变量的配置与更新 1 4 测试安装 1 5 创建虚拟环境 2 安装英伟达驱动 法一 命令行安装 法二 GU
  • 1264 - Out of range value for column 'id' at row 1

    1 我用的是mysql 在数据插入是报错 原因是我插入的值 超过了数据库中类型和长度设置 1 1 我的插入语句 注意 id 的值 INSERT INTO test id sex name username password classes
  • Vue —— 锚点导航

    一个页面中分为多块 例如 目录一 目录二 目录三等 这就需要加上一个锚点导航的需求 提高用户的操作性 原生的写法 div class wrapper ul li a href catalogue1 目录一 a li li a href ca
  • SpringCloud概述

    SpringCloud概述 1 SpringCloud是什么 2 SpringCloud和SpringBoot关系 3 Dubbo和SpringCloud技术选型 4 SpringCloud作用 1 SpringCloud是什么 现代化的J
  • How to compile rocksdb with lz4 support

    On CentOS 6 x or 7 x you can do the following to easily install lz4 using the package manager As root sudo su is your fr
  • 137-----JS基础-----类的操作

    一 代码 不算难 如果后续操作到类的话 可以直接使用下面封装好的接口到自己的tool中
  • 线性回归建模及模型诊断

    目录 一 建模背景及目的及数据源说明 二 描述性分析 2 1 连续自变量与连续因变量的相关性分析 2 2 二分类变量与连续变量的相关性分析 2 3 多分类变量与连续变量的相关性分析 三 模型建立与诊断 3 1 一元线形回归及模型解读 3 2
  • 编码技巧——校验器(职责链+抽象模版)

    日常开发中可能遇到这样的业务场景 请求从入口进来 需要经过层层的校验 通过校验后才会执行业务操作 写操作 RPC 异步消息 这里前置的多层校验流程中 从类型上看 部分是基本参数校验 部分是包含业务逻辑的校验 并且部分校验是可以并行 部分是有
  • 矩阵的分解——LU分解

    LU分解 LU分解是矩阵分解的一种 将一个矩阵分解为一个下三角矩阵和一个上三角矩阵的乘积 有时需要再乘上一个置换矩阵 LU分解可以被视为高斯消元法的矩阵形式 在数值计算上 LU分解经常被用来解线性方程组 且在求逆矩阵和计算行列式中都是一个关
  • OSQP二次规划求解库使用说明

    OSQP二次规划求解库使用说明 贺志国 2023 5 10 1 凸二次规划的一般表达式 m i n 1 2 x
  • 微信API接口访问慢

    场景 项目需要调用微信API接口获得微信用户信息 本地开发和公司测试环境中测试十分顺利 但是在部署到现场环境中 接口调用经常会很慢 需要几分钟的时间才能返回值 现场环境的服务器因为客户原因 只能指定申请特定个别IP访问 无法开放微信接口域名
  • MySQL中常用工具

    作者 小刘在C站 个人主页 小刘主页 努力不一定有回报 但一定会有收获加油 一起努力 共赴美好人生 学习两年总结出的运维经验 以及思科模拟器全套网络实验教程 专栏 云计算技术 小刘私信可以随便问 只要会绝不吝啬 感谢CSDN让你我相遇 目录
  • vue3使用事件委托实现选项卡的切换

    选项卡是js写的 不是组件 ul li item li ul
  • 虚拟机不能上网,ifconfig显示只有lo

    1 开启虚拟机后无法上网 ifconfig查询发现只有本地环回网口 2 使用 ifconfig a 命令查三腊鉴看是否存在网卡 3 查询结果显示系统中存在ens33和ens37网卡 解决方法就是要启动ens33网卡 并配置其IP地址等信息
  • JavaScript面向对象:类的几种继承方式

    面向对象 类的几种继承方式 类与实例 类的声明 生成实例 类与继承 如何实现继承 继承的几种方式 前端小白记录学习笔记 不做他用 类与实例 类的声明 用构造函数模拟类 传统写法 function Person1 name this name