【笔记】【Javascript】javascript实现继承

news2024/11/20 20:30:25

前言

  • 之前写过关于面向对象编程的文章,通过阅读别人的博客了解了一下Javascript实现继承的方法,并且使用图画的形式帮助了解,图是自己做的,若有偏差请读者帮忙指出,谢谢。
  • 笔记中有些个人理解后整理的笔记,可能有所偏差,也恳请读者帮忙指出,谢谢。

免责声明

  • 为了方便,本文中使用的部分图片来自于网络,如有侵权,请联系博主进行删除,感谢其他博主提供的图床。
  • 此笔记用于记录本人对于该知识的汇总。以方便日后的工作与学习。
  • 如有侵权请告知,马上删除。

javascript如何实现继承?

【什么是继承?】

  • 子类拥有父类的特征行为

    • 特征==属性
    • 行为==方法

【怎么做?】

//父类
function Person(name){//给构造函数添加了参数
    this.name = name;
    this.msg = function(){
        alert(this.name);
    }
}
Person.prototype.age = 10;//给构造函数添加了原型属性

方法一:原型链继承

步骤1:创建一个子类,并把子类的原型对象指向父类的实例**(关键点)**

//创建子类
function Sub(){
    this.name = 'roy';
}
//子类的原型对象指向父类实例
Sub.prototype = new Person();

步骤2:创建子类实例,此时子类实例已经完成继承

var sub1 = new Sub();

步骤3:验证是否继承成功(其实真正实现继承仅上面两步即可,这一步属于调用父类,检验是否继承成功)

console.log(sub1.age);//10
//instanceof 判断元素是否在另一个元素的原型链上
//sub1继承了Person的属性,返回true
console.log(sub1 instanceof Person);//true

【分析】

  • 优点
    • 实现了继承
      • √ 实例的构造函数的属性(即子类的构造函数属性)
      • √ 父类的构造函数的属性
      • √ 父类原型的属性
  • 缺点
    • 新实例无法向父类构造函数传参
      • 【原因】步骤二时,是通过子类来创建新实例,而不是通过父类创建实例
    • 继承单一
      • 【原因】如图(1)一个子类仅继承一个父类
    • 修改子类实例的属性会改到父类的属性。
      • 【原因】如图(1)

方法二:构造函数继承

步骤1:在子类构造函数内回调父类构造函数(关键点)

function Sub(){
    Person.call(this,'roy');
    this.age = 12;
}

步骤2:创建子类实例

var sub1 = new Sub();

步骤3:检验是否继承成功

console.log(sub1.name);//roy
console.log(sub1.age);//12
console.log(sub1 instanceof Person);//false

【分析】

  • 优点
    • 实现了继承:
      • √ 继承父类构造函数的属性
      • ✕ 继承父类原型上的属性(如图(3))
    • 可以向父类构造函数传参
  • 缺点
    • 无法实现父类构造函数的复用
      • 【原因】用一次,重新调用父类构造函数一次
    • 每个新实例都有父类构造函数的副本,臃肿
      • 【原因】子类构造函数中产生了闭包,闭包导致内存泄露
    • 无法继承父类原型上的属性
      • 【原因】如图(3)

方法三:组合式继承

步骤1:在子类构造函数内回调父类构造函数**(关键点)**

function Sub(name){
    Person.call(this,name);//构造函数继承
}

步骤2:创建一个子类,并把子类的原型对象指向父类的实例**(关键点)**

Sub.prototype = new Person();//原型链继承

步骤3:创建子类实例,检验是否继承成功

var sub = new Sub('roy');
console.log(sub.name);//roy 继承了构造函数属性
console.log(sub.age);//10 继承了父类原型的属性

【分析】

  • 优点:
    • 实现了继承:
      • √ 继承父类原型上的属性
    • 可以传参,复用
    • 每个新实例引入的构造函数属性是私有的
      • 【原因】步骤1产生了闭包
  • 缺点:
    • 调用了两次父类构造函数,耗内存
    • 子类构造函数会代替原型上的父类的构造函数(不懂的点,欢迎小伙伴在评论区讨论一下)

方法四:ES6 Class类继承

为了统一使用ES6格式父类也进行改动一下(不改动直接用前面的父类也行)

//父类
class Person {//给构造函数添加
  constructor(name) {
    this.name = name;
  }
  msg() {
    alert(this.name);
  }
}
Person.prototype.age = 10;//给构造函数添加了原型属性

步骤1:使用关键字extends继承父类方法和属性,关键字super继承父类构造函数属性(关键点)

class Sub extends Person {  //继承父类方法
  constructor(name) {
    super(name);        //继承父类构造函数属性
    this.sex = 'boy';
  }
}

步骤2:创建子类实例,检验是否继承成功

const sub = new Sub('lao');
console.log(sub.age);    	//10	//证明继承父类构造函数原型属性
console.log(sub.name);   	//lao
console.log(sub.sex); 		//boy
console.log(sub.msg());
console.log(sub instanceof Person);   //true

【分析】

  • 优点:

    • 实现继承
      • √ 继承父类原型上的属性
      • √ 继承父类构造函数的属性
    • 写法更加的简洁
  • 缺点:

    • 函数申明不能自动提升(必须先声明再使用)

      【示例】

      let sub1 = new Sub()	//报错ReferenceError
      class Sub{}
      

方法五:原型式继承

步骤1:通过一个函数来模拟子类构造函数(关键点)

function content(obj){
    function F(){};			//模拟子类的构造函数
    F.prototype = obj;	//将子类构造函数原型对象设为父类实例
    return new F();			//创建子类构造函数实例
}

步骤2:创建父类的实例

var person = new Person();

步骤3:调用模拟子类构造函数来模拟创建子类实例

var sub1 = content(person);

步骤4:检验是否继承成功

console.log(sub1.age);//10 继承了父类函数的属性

【分析】

  • 优点:
    • 无需定义子类,反而使用一个现成的类直接继承。
  • 缺点:
    • 所有实例都会继承父类原型上的属性(如图(4)所示)
    • 无法实现复用(新实例属性都是后面添加的)

PS:Object.create()的原理就是通过原型式继承实现的

【简写】上述原型式继承可如下简写

var person = new Person();
var sub1 = Object.create(person);
console.log(sub1.age);//10 继承了父类函数的属性

方法六:寄生式继承

步骤1:通过一个函数来模拟子类构造函数(关键点)

function content(obj){
    function F(){};
    F.prototype = obj;//继承了传入的参数
    return new F();//返回函数对象
}

步骤2:创建父类实例

var person = new Person();

步骤3:创建一个仅用于封装继承过程的函数,函数的内部以某种方式来继承父类

function subObject(obj){
    var sub = content(obj);//通过调用函数
    sub.name = 'roy';//以某种方式来增强这个对象
  	sub.sayHi=function(){
      console.log('hello');
    }
    return sub;//返回子类
}

步骤4:调用函数来模拟创建子类实例

var sub1 = subObject(person);

步骤5:

console.log(typeof subObject);//function
console.log(typeof sub1);//object
console.log(sub1.name);//'roy' 返回了个sub对象,继承了sub的属性
sub1.sayHi();	//'hello'

【分析】

  • 优点:
    • 为对象添加函数
  • 缺点:
    • 效率低
      • 【原因】不能做到函数复用

方法七:寄生组合继承

步骤1:创建父类,给父类添加方法

function Parent6() {
  this.name = 'parent6';
  this.play = [1, 2, 3];
}
Parent6.prototype.getName = function () {
  return this.name;
}

步骤2:创建子类,回调继承父类属性(关键点)

function Child6() {
  Parent6.call(this);	//继承服父类的属性
  this.friends = 'child6';
}

步骤3:借助函数,父子类关联(关键点)

function clone(parent, child) {
  // 这里改用 Object.create 就可以减少组合继承中多进行一次构造的过程
  child.prototype = Object.create(parent.prototype);
  child.prototype.constructor = child;
}

clone(Parent6, Child6);

PS:子类构造器等于父类对象

【证明】

console.log(child.prototype.constructor == parent); //true

步骤4:给子类追加方法

Child6.prototype.getFriends = function () {
  return this.friends;
}

步骤5:验证继承

let person6 = new Child6();
console.log(person6);	//输出:带有父类属性的对象>>>>>>证明:实现子类继承父类属性
console.log(person6.getName());	//输出:parent6>>>>证明:实现子类继承父类的方法
console.log(person6.getFriends());//输出:child6>>>证明:子类可以追加方法

文献参考

[1] 贪吃的猫,《JS继承》,稀土掘金,2021-04-29

[2] 小小操作手,《js继承》,稀土掘金,2020-06-13

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

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

相关文章

基于STM32的ADC采样及各式滤波实现(HAL库,含VOFA+教程)

前言:本文为手把手教学ADC采样及各式滤波算法的教程,本教程的MCU采用STM32F103ZET6。以HAL库的ADC采样函数为基础进行教学,通过各式常见滤波的实验结果进行分析对比,搭配VOFA工具直观的展示滤波效果。ADC与滤波算法都是嵌入式较为…

MySQL进阶- Linux安装 和 索引

目录 Linux安装索引索引的概述索引的结构索引结构的介绍BtreeBtreeHash 索引的分类索引的语法(创建,查看,删除等)SQL性能分析SQL的执行频率(查看SQL的执行频率)慢查询日志show profilesexplain执行计划 索引…

video标签学习 xgplayer视频播放器分段播放mp4

文章目录 学习链接目标video标签自带视频和制作的视频区别video标签的src属性本地视频文件前端代码播放效果 服务器视频文件示例1后端代码前端代码播放效果 示例2后端代码前端代码播放效果 示例3后端配置前端代码播放效果 video对象video对象创建和获取video的属性video的方法v…

chatgpt赋能python:Python模块安装方法全解析

Python模块安装方法全解析 Python是一种功能强大的编程语言,拥有大量的开源库,这些库是在各种应用程序中使用的重要组件,它们能加速开发过程。不管你是初学者、中级者还是高级者,总会遇到需要安装第三方库的情况。但是安装库是一…

《Java并发编程实战》课程笔记(四)

互斥锁 原子性问题到底该如何解决呢? “同一时刻只有一个线程执行”这个条件非常重要,我们称之为互斥。如果我们能够保证对共享变量的修改是互斥的,那么,无论是单核 CPU 还是多核 CPU,就都能保证原子性了。 锁模型 …

Python连接达梦数据库

python如果想连接达梦数据库,必须要安装dmPython。 简介:dmPython 是 DM 提供的依据 Python DB API version 2.0 中 API 使用规定而开发的数据库访问接口。dmPython 实现这些 API,使 Python 应用程序能够对 DM 数据库进行访问。 dmPython 通…

数据库服务器

数据库服务器,联系Web服务器与DBMS的中间件是负责处理所有的应用程序服务器,包括在web服务器和后台的应用程序或数据库之间的事务处理和数据访问。 基本信息 中文名 数据库服务器 外文名 database server 功能 数据库服务器建立在数据库系统基础上&a…

系统漏洞利用与提权

任务二:系统漏洞利用与提权 任务环境说明: 服务器场景:PYsystem0033 服务器场景操作系统:Ubuntu 服务器场景用户名:未知 密码:未知 1.使用nmap扫描靶机系统,将靶机开放的端口号按从小到大的顺序作为F…

解决Vmware上的kali找不到virtualbox上的靶机的问题

解决kali找不到靶场ip问题的完整方法 1.配置靶机2.配置kali的虚拟网络3.配置kali中的eth0网络 1.配置靶机 靶机部署在Virtualbox上对其进行网络配置,选择连接方式为仅主机(Host-Only)网络。 2.配置kali的虚拟网络 在编辑中选择虚拟网络配…

chatgpt赋能python:Python中浮点数的表示方法

Python中浮点数的表示方法 在Python中,浮点数是一种数字类型,用于表示带有小数点的数值。但是,由于计算机在表示浮点数时存在精度限制,因此需要特别注意。本文将介绍Python中浮点数的表示方法及其可能导致的错误。 Python中浮点…

陕西发布!陕西省重点实验室申报条件类别、认定程序要求

本文整理了陕西省重点实验室申报条件,认定材料等相关内容,感兴趣的朋友快跟小编一起来看看吧! 一、总体思路 本次省重点实验室布局建设工作以填补我省优势学科领域下无省级及以上科学与工程研究类科技创新基地的空白为主,同时兼顾前沿、新兴、…

MySQL基础- 多表查询 和 事务

目录 多表查询多表关系多表查询概述多表查询的分类内连接外连接自连接联合查询union,union all子查询标量子查询列子查询行子查询表子查询 综合练习小结 事务事务简介事务的操作四大特性ACID并发事务问题事务的隔离级别小结 多表查询 之前的SQL语句里的DQL只能进行…

数字图像学笔记 —— 18. 图像抖动算法

文章目录 为什么需要图像抖动图像抖动算法实现的基本思路常见图像抖动算法实现Floyd-Steinberg 抖动算法Atkinson 抖动算法算法实现 为什么需要图像抖动 在数字图像中,为了表示数字图像的细节,像素的颜色深度信息最少也是8位,即 0 − 256 0…

Linux:centos:周期性计划任务管理《crontab》

crontab常用基础属性 -e 编辑计划任务 -l 查看计划任务 -r 删除计划任务 -u 指定用户的计划任务 首先创建一个名为test的用户名 crontab时间规定 格式:分钟 小时 日期 月份 星期 命令 分钟-- 0-59整数 小时 -- 0-23整数 日期 -- 1--31 整数 月份 -- 1-12 整数 星期…

C++ queue类成员介绍

目录 🤔queue模板介绍: 🤔queue特点: 🤔queue内存图解: 🤔 queue的成员函数 🔍queue构造函数: 🔍queue赋值函数: 🔍queue判断函…

黑马Redis视频教程实战篇(三)

目录 一、优惠券秒杀 1.1 全局唯一ID 1.2 Redis实现全局唯一ID 1.3 添加优惠卷 1.4 实现秒杀下单 1.5 库存超卖问题分析 1.6 代码实现乐观锁解决超卖问题 1.7 优惠券秒杀-一人一单 1.8 集群环境下的并发问题 二、分布式锁 2.1 基本原理和实现方式对比 2.2 Redis分布…

js常见面试笔试题

一.js实现距离最近的回文数 给定一个整数 n ,你需要找到与它最近的回文数(不包括自身)。 “最近的”定义为两个整数差的绝对值最小。 示例 1: 输入: "123" 输出: "121" function findNearestPalindrome…

Jenkins+Python自动化测试之持续集成详细教程

前言 今天呢笔者想和大家来聊聊JenkinsPython自动化测试持续集成,废话呢就不多说了哟咱们直接进入主题哟。 一、Jenkins安装 ​ Jenkins是一个开源的软件项目,是基于java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供…

I.MX RT1170加密启动详解(2):Authenticated HAB认证原理

文章目录 1 基础2 使能过程3 Boot flow 1 基础 HAB认证是基于RSA或ECDSA算法的公钥密码学,它用一系列的私钥对image进行加密,然后BootROM在上电后用对应的公钥验证加密的镜像是否被修改。这个密钥结构就是PKI(Public Key Infrastructure)树 (1)normal …

chatgpt赋能python:Python中画笔颜色的函数介绍

Python中画笔颜色的函数介绍 在Python中,我们可以使用turtle模块来绘制图形,其中画笔颜色是非常重要的一部分。画笔颜色可以决定图形的风格和色调,是图形表现的关键因素之一。Python中提供了几种方法来设置画笔颜色。 1. 设置画笔颜色的函数…