当前位置: 首页 > news >正文

如何理解原型及原型链?js的继承方式

原型与原型链

  1. 原型
    在js中,每个对象都有一个原型(prototype)。原型是一个对象,其他对象可以通过原型来共享属性和方法。当我们创建一个对象时,它会自动关联到一个原型对象。
    例如:
    function Person(name, age) {
    this.name = name;
    this.age = age;
    }// 在 Person 构造函数的原型上添加一个 greet 方法
    Person.prototype.greet = function() {
    console.log(`Hello, my name is ${this.name}.`);
    };const person1 = new Person('Alice', 30);
    const person2 = new Person('Bob', 25);person1.greet(); // 输出 "Hello, my name is Alice."
    person2.greet(); // 输出 "Hello, my name is Bob."
    
    在上面的代码中,创建了一个Person对象,有通过person创建了person1和person2对象,这两个对象都关联到 Person.prototype 原型对象,并且可以共享 greet 方法。
  2. 原型链
    原型链是福哦个对象通过原型链条连接在一起的数据结构。当访问一个对象的属性或方法时,js引擎会先在对象本身中寻找,如果找不到,就会沿着原型链继续找,知道找到该属性或方法,或者达到原型链的顶端(Object.prototype )。
    举个例子:
function Person(name, age) {this.name = name;this.age = age;
}Person.prototype.greet = function() {console.log(`Hello, my name is ${this.name}.`);
};const person1 = new Person('Alice', 30);console.log(person1.toString()); // 输出 "[object Object]"

在这个例子中 person1通过原型链继承了toString方法。
所以是Object.prototype原型链的顶端,它是所有对象的原型,包括内置对象和自定义对象。当查找属性或方法时,原型链会一直往上查找,直到 Object.prototype。如果在整个原型链上都找不到该属性或方法,则返回 undefined

原型链继承

原型继承是通过原型链来实现对象间的属性和方法共享。在原型继承中,一个对象可以从另一个对象继承属性和方法,这样可以实现对象之间的复用和扩展。

原型继承的基本概念如下:

  1. 每个 JavaScript 对象都有一个原型对象(prototype),它是一个普通对象。
  2. 当访问一个对象的属性或方法时,如果该对象本身没有该属性或方法,JavaScript 引擎会沿着原型链向上查找,直到找到为止。
  3. 原型链是由多个对象通过原型关联形成的链条,最终的原型对象通常是 Object.prototype,它是 JavaScript 中所有对象的原型。
  4. 如果在整个原型链上都找不到该属性或方法,则返回 undefined

在原型继承中,我们可以通过构造函数的原型对象来共享属性和方法。当使用 new 关键字调用构造函数创建对象时,新对象会关联到该构造函数的原型,从而继承原型上的属性和方法。

下面是一个使用原型继承的简单示例:

// 定义一个 Person 构造函数
function Person(name) {this.name = name;
}// 在 Person 的原型上添加一个 greet 方法
Person.prototype.greet = function() {console.log(`Hello, my name is ${this.name}.`);
};// 使用 Person 构造函数创建两个对象
const person1 = new Person('Alice');
const person2 = new Person('Bob');// 调用对象的 greet 方法
person1.greet(); // 输出 "Hello, my name is Alice."
person2.greet(); // 输出 "Hello, my name is Bob."

在上面的代码中,Person 构造函数的原型对象上有一个 greet 方法,通过 new Person() 创建的对象(例如 person1person2)会共享这个方法。这样,我们可以通过原型继承在多个对象之间共享方法,提高代码的重用性和可维护性。

需要注意的是,原型继承只能继承原型上的属性和方法,而不能继承构造函数内部的局部变量。如果需要更灵活的继承方式,可以考虑其他方式,例如组合继承、原型式继承、寄生式继承等。

js的其他继承方式

  1. 组合继承
    组合继承时结合了原型链继承和构造函数继承的一种继承方式。他通过在给子类的构造函数中调用父类的构造函数来继承父类的属性,并通过将子类的原型指向一个新的创建的父类对象来继承的方法。
function Parent(name) {this.name = name;
}Parent.prototype.greet = function() {console.log(`Hello, my name is ${this.name}.`);
};function Child(name, age) {Parent.call(this, name); // 构造函数继承this.age = age;
}Child.prototype = Object.create(Parent.prototype); // 原型链继承
Child.prototype.constructor = Child;const child = new Child('Alice', 5);
child.greet(); // 输出 "Hello, my name is Alice."
  1. 寄生式继承
    寄生式继承是在原型式的基础上增强新对象,添加额外的属性和方法。
function createPerson(proto, age) {const newPerson = createObject(proto); // 原型式继承newPerson.age = age; // 增强对象newPerson.introduce = function() {console.log(`I am ${this.name} and I am ${this.age} years old.`);};return newPerson;
}const person = {name: 'Alice',greet: function() {console.log(`Hello, my name is ${this.name}.`);}
};const newPerson = createPerson(person, 30);
newPerson.greet(); // 输出 "Hello, my name is Alice."
newPerson.introduce(); // 输出 "I am Alice and I am 30 years old."
  1. 寄生组合式继承
    寄生组合式继承是对组合继承的一种优化,通过构造函数继承属性,同时利用Object.create()方法来继承原型,避免了调用父类构造函数时产生的不必要的属性重复赋值问题。
function Parent(name) {this.name = name;
}Parent.prototype.greet = function() {console.log(`Hello, my name is ${this.name}.`);
};function Child(name, age) {Parent.call(this, name); // 构造函数继承this.age = age;
}Child.prototype = Object.create(Parent.prototype); // 原型链继承
Child.prototype.constructor = Child;const child = new Child('Alice', 5);
child.greet(); // 输出 "Hello, my name is Alice."
  1. 构造函数式继承
function Animal(name) {this.name = name;
}function Dog(name, breed) {Animal.call(this, name);this.breed = breed;
}const dog = new Dog('Buddy', 'Golden Retriever');
console.log(dog.name); // 输出 "Buddy"

相关文章:

如何理解原型及原型链?js的继承方式

原型与原型链 原型 在js中,每个对象都有一个原型(prototype)。原型是一个对象,其他对象可以通过原型来共享属性和方法。当我们创建一个对象时,它会自动关联到一个原型对象。 例如:function Person(name, a…...

C# 按表格中的某列排序/查询

using System; using System.Data; using System.Linq;class Program {static void Main(){// 创建一个示例的 DataTable 对象DataTable table new DataTable();table.Columns.Add("ID", typeof(int));table.Columns.Add("Name", typeof(string));table.R…...

【Vue】】img使用 :src 动态绑定图片地址,但是加载图片不成功

问题复现&#xff1a; img标签直接动态绑定图片的相对路径的时候&#xff0c;图片不能正常显示。代码如下所示 <view style"margin: 20rpx" v-for"(item, index) in showSampleImage" :key"index"><u-image :src"item.src"…...

list模拟

之前模拟了string,vector&#xff0c;再到现在的list&#xff0c;list的迭代器封装最让我影响深刻。本次模拟的list是双向带头节点的循环链表&#xff0c;该结构虽然看起来比较复杂&#xff0c;但是却非常有利于我们做删除节点的操作&#xff0c;结构图如下。 由于其节点结构特…...

python字典:怎么取出key对应的值

目录 python中的字典是什么 怎么判断key是否在字典中 怎么取出key对应的值 总结 python中的字典是什么 在Python中&#xff0c;字典&#xff08;Dictionary&#xff09;是一种无序且可变的数据类型&#xff0c;用于存储键-值&#xff08;Key-Value&#xff09;对。字典通过…...

okvis

论文 Keyframe-Based Visual-Inertial SLAM Using Nonlinear Optimization 摘要 由于两种感知模式的互补性&#xff0c;视觉和惯性线索的融合在机器人中变得很流行。虽然迄今为止大多数融合策略都依赖于过滤方案&#xff0c;但视觉机器人界最近转向了非线性优化方法&#x…...

fabric js双击弹出菜单, 双击弹出输入框 修改文字 群组对象

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>测试1</title><style type"text/css">body {background-color: #ccc;float: left;}#main {background-color: #fff;border: 1px…...

路由器工作原理

路由器原理 路由概述 路由&#xff1a;跨越从源主机到目标主机的一个互联网络来转发数据包的过程。&#xff08;为数据包选择路径的过程&#xff09; 作用&#xff1a;路由器是连接不同网段的。 转发依据&#xff1a; 路由表&#xff1a;路径选择全看路由表&#xff0c;根…...

在centos 7系统docker上构建mysql 5.7

一、VM上已经安装centos 7.9&#xff0c;且已完成docker的构建 二、安装mysql5.7 安装镜像&#xff1a;[rootlocalhost lll]# docker pull mysql:5.7 查看镜像[rootlocalhost lll]# docker images 根据镜像id构建mysql容器&#xff0c;且分配端口号[rootlocalhost lll]# dock…...

数据库的介绍和分类

目录 一、数据库的介绍和分类 二、命令行客户端 三、数据操作 四、查询的基本操作 五、条件查询 六、分组和聚合 资料获取方法 一、数据库的介绍和分类 数据库&#xff1a;长期存储在计算机内、有组织的数据集合 数据库的分类&#xff1a; 关系型数据库 以表格的形式…...

职责链模式——请求的链式处理

1、简介 1.1、概述 很多情况下&#xff0c;在一个软件系统中可以处理某个请求的对象不止一个。例如SCM系统中的采购单审批&#xff0c;主任、副董事长、董事长和董事会都可以处理采购单&#xff0c;他们可以构成一条处理采购单的链式结构。采购单沿着这条链进行传递&#xff…...

docker中涉及的挂载点总结

文章目录 1.场景描述2. 容器信息在主机上位置3. 通过docker run 命令4、通过Dockerfile创建挂载点5、容器共享卷&#xff08;挂载点&#xff09;6、最佳实践&#xff1a;数据容器 1.场景描述 在介绍VOLUME指令之前&#xff0c;我们来看下如下场景需求&#xff1a; 1&#xff…...

elasticsearch 官方优化建议

.一般建议 a.不要返回过大的结果集。这个建议对一般数据库都是适用的&#xff0c;如果要获取大量结果&#xff0c;可以使用search_after api&#xff0c;或者scroll &#xff08;新版本中已经不推荐&#xff09;。 b.避免大的文档。 2. 如何提高索引速度 a.使用批量请求。为了…...

Kubernetes(K8s)从入门到精通系列之五:K8s的基本概念和术语之应用类

Kubernetes K8s从入门到精通系列之五:K8s的基本概念和术语之应用类 一、Service与Pod二、Label与标签选择器三、Pod与Deployment四、Service的ClusterIP地址五、Service的外网访问问题六、有状态的应用集群七、批处理应用八、应用配置问题九、应用的运维一、Service与Pod Ser…...

DevOps(四)

CD(二) 1. CDStep 1 - 上传代码Step 2 - 下载代码Step 3 - 检查代码Step 4 - 编译代码Step 5 - 上传仓库Step 6 - 下载软件Step 7 - 制作镜像Step 8 - 上传镜像Step 9 - 部署服务2. 整体预览2.1 预览1. 修改代码2. 查看sonarqube检查结果3. 查看nexus仓库4. 查看harbor仓库5.…...

Element-plus侧边栏踩坑

问题描述 el-menu直接嵌套el-menu-item菜单&#xff0c;折叠时不会出现文字显示和小箭头无法隐藏的问题&#xff0c;但是实际开发需求中难免需要把el-menu-item封装为组件 解决 vue3项目中嵌套两层template <template><template v-for"item in list" :k…...

支持多种通信方式和协议方便接入第三方服务器或云平台

2路RS485串口是一种常用的通信接口&#xff0c;可以支持Modbus Slave协议&#xff0c;并可接入SCADA、HMI、DSC、PLC等上位机。它还支持Modbus RTU Master协议&#xff0c;可用于扩展多达48个Modbus Slave设备&#xff0c;如Modbus RTU远程数据采集模块、电表、水表、柴油发电机…...

使用 OpenCV 进行图像模糊度检测(拉普拉斯方差方法)

写在前面 工作中遇到&#xff0c;简单整理人脸识别中&#xff0c;对于模糊程度较高的图像数据&#xff0c;识别率低&#xff0c;错误率高。虽然使用 AdaFace 模型&#xff0c;对低质量人脸表现尤为突出。但是还是需要对 模糊程度高的图像进行丢弃处理当前通过阈值分类&#xff…...

神经网络简单介绍

人工神经网络(artififial neural network) 简称神经网络&#xff0c;它是一种模仿生物神经网络结构和功能的非线性数学模型。 神经网络通过输入层接受原始特征信息&#xff0c;再通过隐藏层进行特征信息的加工和提取&#xff0c;最后通过输出层输出结果。 根据需要神经网络可以…...

16位S912ZVML32F3MKH、S912ZVML31F1WKF、S912ZVML31F1MKH混合信号MCU,适用于汽车和工业电机控制应用。

S12 MagniV微控制器是易于使用且高度集成的混合信号MCU&#xff0c;非常适合用于汽车和工业应用。S12 MagniV MCU提供单芯片解决方案&#xff0c;是基于成熟的S12技术的完整系统级封装 (SiP) 解决方案&#xff0c;在整个产品组合内软件和工具都兼容。 S12 MagniV系统级封装 (S…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...