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

原型、原型链、__proto__与prototype的区别、继承

一.什么是原型与原型链

根据MDN官方解释: JavaScript 常被描述为一种基于原型的语言——每个对象拥有一个原型对象[[Prototype]] ,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。

以前可以通过__proto__访问原型,但现在它已经从相关web标准中被移除,后续可通过Object.getPrototypeOf(obj)来获取原型。在 javascript 中,函数可以有属性。每个函数都有一个特殊的属性叫作原型(prototype),而它主要是用作继承

二.原型的作用

之所以存在原型,是因为JS语言需要实现面向对象,而原型是面向对象的实现手段之一。一个能支持面向对象的语言必须做到一点:能判断一个实例的类型. 在JS中,通过原型就可以知晓某个对象从属于哪个类型,换句话说,原型的存在避免了类型的丢失。在使用方面,有了原型就可以抽离实例的公共方法到原型上,这样就避免了把方法放到实例中,从而减少了内存的消耗。

三.隐式原型和显示原型的区别

在过去我们常用__proto__表示隐式原型(它其实就是[[Prototype]])。用prototype代表显示原型。
每个对象(数组,对象,函数)都有自己的__proto__,通过__proto__可以添加数据到原型,也可以通过它一层一层查找数据。构造函数默认会有prototype属性,prototype属性是用来继承的,实例化之后__proto会指向构造函数的prototype。

四.JS的继承

父类

function Person(name) {this.name = namethis.say = function () {console.log('1 + 1 = 2')}this.colors = ["red", "blue", "green"];
}Person.prototype.listen = function () {console.log('エウテルペ')
}Person.prototype.sayName = function () { // 父类原型方法return this.name;};

4.1 原型继承

将父类的实例作为子类的原型

缺点:

  • 无法实现多继承,即一个子类不能同时继承多个父类
  • 所有实例共享同一个父类的原型,修改子类的原型会影响父类的原型
  • 创建子类实例时,无法向父类构造函数传参
// TODO:思路:将父类的实例作为子类的原型
function Student() {this.type = "学生"this.name = "张三"
}Student.prototype = new Person('人') //TODO:关键点 通过原型继承父类 =>无法实现多继承,即一个子类不能同时继承多个父类
Student.prototype.xx = 123
Student.prototype.fn = ()=>{}const zhangsan = new Student()
console.log(zhangsan);Person.prototype.eat = function () {console.log('吃东西')
}
console.log(zhangsan);// TODO:缺点
// 1 无法实现多继承,即一个子类不能同时继承多个父类
// 2 所有实例共享同一个父类的原型
function Student2() {this.type = "学生"this.name = "张三"
}
Student2.prototype = new Person('人2')
// 3 创建子类实例时,无法向父类构造函数传参
const lisi = new Student2()

4.2 构造继承

在子类的构造函数内部调用父类构造函数并改变构造函数的this指向。

缺点:

  • 父类原型上的属性没有继承过来
  • 因为原型没有继承过来所以无法实现函数复用,每个子类都有父类构造函数的副本,影响性能
  • 实例并不是父类的实例,只是子类的实例
// TODO:思路:在子类型的构造函数内部调用父类构造函数并改变构造函数的this指向。
function Student(name) {// this.person = new Person(name)Person.call(this,name) // TODO:关键点this.age = 16
}
Student.prototype.run = '跑路'
const lisi = new Student('李四') // 能实现多继承 可以向父类传递参数
// 优点
// 解决了所有实例共享同一个父类的原型,实现多继承,创建子类实例时,可以向父类传递参数
// TODO:缺点
// 1 父类原型上的属性没有继承过来
function Student2(name) {Person.call(this,name)this.age = 18
}
// 2 因为原型没有继承过来所以无法实现函数复用,每个子类都有父类构造函数的副本,影响性能// 3 实例并不是父类的实例,只是子类的实例(只是实例化了Student,根本就没有实例化Person)
const zhangsan = new Student('张大帅')

4.3 组合继承

顾名思义,组合继承就是将原型链继承与构造函数继承组合在一起,从而发挥两者之长的一种继承模式。

缺点:

  • 所有实例共享同一个父类的原型,修改子类的原型会影响父类的原型
  • 调用了两次父类的构造函数
// TODO:思路:顾名思义,组合继承就是将原型链继承与构造函数继承组合在一起,从而发挥两者之长的一种继承模式。
function Student(name, subName) {Person.call(this, name) // 构造继承 第一次调用构造函数this.subName = subName;
}
Student.prototype = new Person() // TODO:关键点 原型继承 第二次调用构造函数
// Student.prototype = Person.prototype
Student.prototype.constructor = Student // 组合继承需要修复构造函数指向?
Student.prototype.saySubName = function () { // 子类原型方法return this.subName;
}// 子类实例
let instance = new Student('王五', 'sisterAn')
instance.colors.push('black')
console.log(instance.colors) // ["red", "blue", "green", "black"]
console.log(instance.sayName()) // 王五
console.log(instance.saySubName()) // sisterAn
console.log(instance);let instance1 = new Student('赵六', 'sisterAn1')
console.log(instance1.colors) //  ["red", "blue", "green"]
console.log(instance1.sayName()) // 赵六
console.log(instance1.saySubName()) // sisterAn1
console.log(instance1);
// 优点:解决了构造继承的缺陷,可以继承原型属性/方法,实现复用
// TODO:缺点:调用了两次父类的构造函数

4.4 寄生组合继承

通过原型链的混成形式来继承方法,在组合继承的基础上.利用 Object.create() 将Person.prototype通过原型的方式继承给一个对象,这样的访问顺序就还是保持子类优先,同时后续添加原型也不会影响父类的原型

优点:

  • 解决了组合继承的缺陷,只调用一次父类的构造函数
  • 修改子类的原型,父类不变

补充

  • Student.prototype.isPrototypeOf(instance)
    • 用于检测构造函数Student.prototype是否存在于另一个对象instance的原型链上
  • instance instanceof Student
    • 用于检测实例对象instance的原型链上是否存在构造函数Student的 prototype。
// TODO:思路:通过原型链的混成形式来继承方法
function Student(name, subName) {Person.call(this, name) // 构造继承this.subName = subName;
}
// 用 Object.create() 将参数1通过原型的方式继承给参数2,这样的访问顺序就还是保持子类优先,同时后续添加原型也不会影响父类的原型
console.log(Object.create(Person.prototype));
Student.prototype = Object.create(Person.prototype, {varB : {value: null,enumerable: true,configurable: true,writable: true},doSomething : {value: function(){ // overrideA.prototype.doSomething.apply(this, arguments);// call super// ...},enumerable: true,configurable: true,writable: true}}); // TODO:关键点
Student.prototype.constructor = Student // 组合继承需要修复构造函数指向// 子类实例
let instance = new Student('王五', 'sisterAn')
instance.colors.push('black')
console.log(instance.colors) // ["red", "blue", "green", "black"]
console.log(instance.sayName()) // 王五
console.log(instance.doSomething())
console.log(instance);let instance1 = new Student('赵六', 'sisterAn1')
console.log(instance1.colors) //  ["red", "blue", "green"]
console.log(instance1.sayName()) // 赵六
console.log(instance1.doSomething())
console.log(instance1);
// 优点:解决了组合继承的缺陷,只调用一次父类的构造函数,原型链保持不变
// Student.prototype.isPrototypeOf(instance) true // 用于检测构造函数Student.prototype是否存在于另一个对象instance的原型链上
// instance instanceof Student // 用于检测实例对象instance的原型链上是否存在构造函数Student的 prototype。

4.5 ES6继承

可以理解ES6继承就是组合寄生继承的一个语法糖.

使用

class People {constructor(name) {this.name = name}run() { }
}// extends 相当于方法的继承
// 替换了上面的3行代码
class Man extends People {constructor(name) {// super 相当于属性的继承// 替换了 People.call(this, name)super(name)this.gender = '男'}fight() { }
}

extends 继承的核心代码如下,其实和寄生组合式继承方式一样

function _inherits(subType, superType) {// 创建对象,Object.create 创建父类原型的一个副本// 增强对象,弥补因重写原型而失去的默认的 constructor 属性// 指定对象,将新创建的对象赋值给子类的原型 subType.prototypesubType.prototype = Object.create(superType && superType.prototype, {constructor: { // 重写 constructorvalue: subType,enumerable: false,writable: true,configurable: true}});if (superType) {Object.setPrototypeOf? Object.setPrototypeOf(subType, superType): subType.__proto__ = superType;}
}

五.关于Object.prototype.__proto__已经弃用

后续可通过Object.getPrototypeOf(obj)来获取原型!
在这里插入图片描述

示例

let Circle = function () {};
let shape = {};
let circle = new Circle();// 设置该对象的原型链引用
// 过时且不推荐使用的。这里只是举个例子,尽量不要在生产环境中这样做。
shape.__proto__ = circle;// 判断该对象的原型链引用是否属于 circle
console.log(shape.__proto__ === circle); // true

相关文章:

原型、原型链、__proto__与prototype的区别、继承

一.什么是原型与原型链 根据MDN官方解释: JavaScript 常被描述为一种基于原型的语言——每个对象拥有一个原型对象[[Prototype]] ,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类…...

前端 面经

1说一说cookie sessionStorage localStorage 区别?解题思路得分点 数据存储位置、生命周期、存储大小、写入方式、数据共享、发送请求时是否携带、应用场景 标准回答 Cookie、SessionStorage、 LocalStorage都是浏览器的本地存储。 它们的共同点:都是存储…...

[oeasy]python0080_设置RGB颜色_24bit_24位真彩色_颜色设置

RGB颜色 回忆上次内容 上次 首先了解了 索引颜色 \33[38;5;XXXm 设置 前景为索引色\33[48;5;XXXm 设置 背景为索引色 RGB每种颜色 可选0-5总共 6 级 想用 精确RGB值 真实地 大红色画个 大红桃心 ♥️ 有可能吗??🤔 rgb 模式 关于 RGB 模式…...

实战项目-用户评论数据情绪分析

目录1、基于词典的方法2、基于词袋或 Word2Vec 的方法2.1 词袋模型2.2 Word2Vec3、案例:用户评论情绪分析3.1 数据读取3.2 语料库分词处理3.3 Word2Vec 处理3.4 训练情绪分类模型3.5 对评论数据进行情绪判断目的:去判断一段文本、评论的情绪偏向在这里&a…...

day02 DOS(续)文本编辑快捷键 发展史

day02课堂笔记 1、常用的DOS命令(续) 1.1、del命令,删除一个或者多个文件 删除T1.class文件 C:\Users\Administrator>del T1.class 删除所有.class结尾的文件,支持模糊匹配 C:\Users\Administrator>del *.class T1.classT1…...

arm64与aarch64

结论: 目前arm64和aarch64概念已合并,新版64位arm程序统称aarch64. 问题引入: 存在部分机器,安装arm版本ss,会报错,提示 rootlocalhost ~]# rpm -ivh senseshiel50 59130arm64.rpm Verifying... ########…...

QString详解

QString存储16位Qchar(Unicode)字符串 QString使用隐式共享(copy-on-write)来提高性能。 什么是Unicode? unicode是一种国际标准,支持当今使用的大多数操作系统,他是US-ASCII和Latin-1的超集(与子集相同字符编码相同…...

SpringCloud微服务

一、微服务架构 1.1、单体应用架构 将项目所有模块(功能)打成jar或者war,然后部署一个进程 优点: 1:部署简单:由于是完整的结构体,可以直接部署在一个服务器上即可。 2:技术单一:项目不需要复杂的技术栈,往往一套熟悉的技术栈就可以完成开…...

Hive 连接及使用

1. 连接 有三种方式连接 hive: cli:直接输入 bin/hive 就可以进入 clihiveserver2、beelinewebui 1.1 hiveserver2/beeline 1、开启 hiveserver2 服务 // 前台运行,当 beeline 输入命令时,服务端会返回 OK [roothadoop1 bin]…...

android libavb深入解读

1、vbmeta结构解析 2、 libavb代码解读 代码地址https://cs.android.com/android/platform/superproject/+/master:external/avb/libavb/ 解析参考AVB源码学习(四):AVB2.0-libavb库介绍1_摸肚子的小胖子的博客-CSDN博客 这篇blog将会更加深入,掌握avb流程。 2.1、avb_slot_…...

【面试题】对闭包的理解?什么是闭包?

大厂面试题分享 面试题库后端面试题库 (面试必备) 推荐:★★★★★地址:前端面试题库闭包的背景由于js中只有两种作用域,全局作用域和函数作用域,而在开发场景下,将变量暴露在全局作用域下的时候…...

笔试题-2023-乐鑫-数字IC设计【纯净题目版】

回到首页:2023 数字IC设计秋招复盘——数十家公司笔试题、面试实录 推荐内容:数字IC设计学习比较实用的资料推荐 题目背景 笔试时间:2022.09.01应聘岗位:数字IC设计工程师笔试时长:60min笔试平台:nowcoder牛客网题目类型:单选题(2道)、不定项选择题(7题)、问答题(…...

antd日期组件时间范围动态跟随

这周遇到了一个很诡异但又很合理的需求。掉了一周头发,死了很多脑细胞终于上线了。必须总结一下,不然对不起自己哈哈哈。 一、需求描述 默认当前日期时间不可清空。 功能 默认时间如下: 目的:将时间改为 2014-08-01 ~ 2014-08…...

mysql一条sql语句的执行过程

sql的具体执行过程 客户端发送一条查询给服务器服务器下先检查查询缓存,如果命中了缓存,返回缓存中的结果否则就需要服务器端进行sql的解析、预处理,再由优化器生成对应的执行计划根据执行计划,调用存储引擎的api来执行查询将结果…...

SaaS是什么,和多租户有什么关系?

空间数据又称几何数据,用来表示物体的位置,形态,大小分布等各方面的信息,是对现实世界中存在的具有定位意义的事物和现象的定量描述。 多租户是SaaS领域特有的产物。 SaaS服务是部署在云上的,客户可以按需购买&#…...

C语言---字符串函数总结

🚀write in front🚀 📝个人主页:认真写博客的夏目浅石. 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝 📣系列专栏:夏目的C语言宝藏 💬总结:希望你看完之…...

MySQL-表的基本操作

一、创建数据表创建数据表是指在已经创建好的数据库中建立新表。创建数据表的过程是规定数据列的属性的过程&#xff0c;同时也是实施数据完整性约束的过程。创建表之前应先使用语句{use 数据库名} 进入到指定的数据库&#xff0c;再执行表操作。创建表语法:CREATE TABLE <表…...

开篇之作—闲聊几句AUTOSAR

背景信息 步入职场已有些许年头,遇到过不少的人,经历过不算多的事情,也走过一些地方。现在坐下来想想,觉得一路走过总是行色匆匆,都来不及停下来驻足路边的风景,抑或是回头看看身后的精彩。 现在有些庆幸的是,加入了这个汽车这个行业,从事着汽车电子开发领域,也因此…...

02- 天池工业蒸汽量项目实战 (项目二)

忽略警告: warnings.filterwarnings("ignore") import warnings warnings.filterwarnings("ignore") 读取文件格式: pd.read_csv(train_data_file, sep\t) # 注意sep 是 , , 还是\ttrain_data.info() # 查看是否存在空数据及数据类型train_data.desc…...

LeetCode-111. 二叉树的最小深度

目录题目分析递归法题目来源111. 二叉树的最小深度题目分析 这道题目容易联想到104题的最大深度&#xff0c;把代码搬过来 class Solution {public int minDepth(TreeNode root) {return dfs(root);}public static int dfs(TreeNode root){if(root null){return 0;}int left…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

【堆垛策略】设计方法

堆垛策略的设计是积木堆叠系统的核心&#xff0c;直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法&#xff0c;涵盖基础规则、优化算法和容错机制&#xff1a; 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则&#xff1a; 大尺寸/重量积木在下&#xf…...

自然语言处理——文本分类

文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益&#xff08;IG&#xff09; 分类器设计贝叶斯理论&#xff1a;线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别&#xff0c; 有单标签多类别文本分类和多…...

Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解

文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一&#xff1a;HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二&#xff1a;Floyd 快慢指针法&#xff08;…...

基于单片机的宠物屋智能系统设计与实现(论文+源码)

本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢&#xff0c;连接红外测温传感器&#xff0c;可实时精准捕捉宠物体温变化&#xff0c;以便及时发现健康异常&#xff1b;水位检测传感器时刻监测饮用水余量&#xff0c;防止宠物…...