简述 JavaScript 中 prototype
简述 JavaScript 中 prototype
这篇笔记主要捋一下这么几个概念:
- JS 的继承
- 构造函数
new的作用及简易实现__proto__&prototype- 同样的方法,class 和 prototype 中分别是怎么实现的
基础概念
JS 是通过 prototype chaining 实现继承的语言,所有的基类都会绑定在 prototype chain 上如:
class Base {constructor() {}
}class Extended extends Base {constructor() {super();}
}class Descendant extends Extended {constructor() {super();}
}const descedant = new Descendant();
console.log(descedant.__proto__);
__proto__ 本身就暴露了当前对象的 [[Prototype]],它所指向的是另一个对象,也就是 prototype chain 上的继承 (粗暴的理解一下就是父类)。返回的对象又可以通过调用 __proto__ 继续获得父类的 [[Prototype]],一步步向上追溯一直到 [[Prototype]] 为 null 为止,一般到这个时候,也是获取到 Object 了——JS 之中,除了 primitive type,万物皆对象。
需要注意的是,__proto__ 返回的对象是 [[Prototype]] 也是 <prototype>,二者是一样的,只不过前者是 chrome 的称呼,后者是 Firefox 的,这里为了一致就使用 [[Prototype]]。获取当前 [[Prototype]] 的方法有两种:
-
__proto__已经 Deprecated 了,deno 中甚至不支持实现
-
Object.getPrototypeOf()/Reflect.getPrototypeOf()推荐使用这个函数
构造函数
class 是 ES6 新出的语法糖,在 ES6 之前都是使用构造函数去实现的,如:
function Person(name, age) {this.name = name;this.age = age;
}// equivalent to
class Person {constructor(name, age) {this.name = name;this.age = age;}
}
实现结果都是一致的:

同样,constructor 也不是一定需要大写,小写也是可以实现同样的功能:
function person3(name, age) {this.name = name;this.age = age;
}const person3Instance = new person3('Deborah', 99);
console.log(person3Instance);

大写只是一个约定俗成的规范。
new 关键字
new 在使用构造函数的时候是必须的,否则它只是返回了一个 undefined:
function Person(name, age) {this.name = name;this.age = age;this.greet = function () {console.log('Hi there');};
}const person = Person('Tylor', 26);
console.log(person);
person.greet();

new 的作用在于
- 它创建了一个新的对象
- 它关联了对应的原型链继承
- 它绑定了
this的指向 - 它执行了构造函数内的部分
一个简单的实现 new 的函数为:
function myNew(constructorFn, ...args) {// 创建一个新的对象const obj = {};// 关联对应的原型链继承Object.setPrototypeOf(obj, constructorFn.prototype);// 执行了构造函数,同时使用 apply 也确定了 this 的指向const res = constructorFn.apply(obj, args);return typeof res === 'object' && res !== null ? res : obj;
}

__proto__ 和 prototype 的区别
简单的说就是,__proto__ 作用于实例上,而 prototype 作用于构造函数上。
如,准确的说函数的实现不是像上面那样实现的,而是:
Person.prototype.greet = function () {console.log(`Hi there, I am ${this.name},and I am ${this.age} years old`);
};
从自动提示上也可以看到,实例化的对象是无法访问内部的 [[Prototype]] 的:


另外,所有的函数实现其实都是绑定在 prototype 上的:

主要的原因就是因为函数本质上也是对象,而在每次实例化的时候都创建一个新的对象,是一个非常昂贵的事情。因此 JS 会将函数绑定到 [[Prototype]] 上,这样所有的实例化的对象可以共享一个函数。
如果想要每次实例化的时候都创建一个新的函数,则可以使用 arrow function(在 class 中使用),这也是 ES6 语法的 pro and con 了。
super 与 this
到这一步,基本上使用 prototype 去实现 class 都实现的差不多了,除了继承这一部分,以下面代码为例:
class Parent {constructor() {this.name = 'parent';}greet() {console.log(`This is ${this.name}`);}
}class Child extends Parent {constructor() {this.name = 'Child';}greet() {}
}const child = new Child();
事实上 JS 会报错:

在当调用了 super 之后就会发现,this 的指向被绑定到了 Child 中:
class Parent {constructor() {this.name = 'parent';}greet() {console.log(`This is ${this.name}`);}
}class Child extends Parent {constructor() {super();this.name = 'Child';}greet() {super.greet();}
}const child = new Child();
child.greet();

接下来要模拟实现的就是这一步,其中需要注意的就是:
-
实现继承关系
这点可以通过修改
prototype进行实现,已知[[Prototype]]中包含了所有的 prototype chain,这里也只需要将Child.prototype指向Parent.prototype,并且绑定对应的 构造函数即可。 -
修改
this的指向
function Parent() {this.name = 'Parent';
}Parent.prototype.greet = function () {console.log(`This is ${this.name}`);
};function Child() {// bind child to parentParent.call(this);this.name = 'Child';
}// set up inheritance
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;Child.prototype.greet = function () {Parent.prototype.greet.call(this);
};const child = new Child();
child.greet();

这样,prototype 中的继承关系也实现了。
这也是为什么 JS 推荐使用 class 而非重新实现一个 prototype 的原因,主要还是因为使用 class 的代码更加简洁易读。
相关文章:
简述 JavaScript 中 prototype
简述 JavaScript 中 prototype 这篇笔记主要捋一下这么几个概念: JS 的继承构造函数new 的作用及简易实现__proto__ & prototype同样的方法,class 和 prototype 中分别是怎么实现的 基础概念 JS 是通过 prototype chaining 实现继承的语言&#…...
一觉醒来Chat gpt就被淘汰了
目录 什么是Auto GPT? 与其他语言生成模型相比,Auto GPT具有以下优点 Auto GPT的能力 Auto GPT的能力非常强大,它可以应用于各种文本生成场景,包括但不限于以下几个方面 Auto GPT的历史 马斯克说:“ChatGPT 好得吓…...
13款JavaScript图像处理库,建议收藏备用
pica: 一个在浏览器中调整图像大小,而不会出现像素失真,处理速度非常快的图片处理库,仓库地址https://github.com/nodeca/picahtml2canvas: 强大的使用js开发的浏览器网页截图工具,仓库地址https://github.…...
uniapp m3u8格式视频加载
uniapp一:mui-player:三方 h5 web app uniapp 使用 mui-player 插件播放 m3u8/flv 视频流_翘翘红的博客-CSDN博客 uniapp 开发的h5项目,需要播放m3u8/flv后缀的视频,网上有很多视频插件,但是样式和效果不尽如人意&am…...
iOS描述文件(.mobileprovision)一键申请
iOS描述文件(.mobileprovision)一键申请 在主界面上点击描述文件按钮。 新建ios描述文件 然后点击新建,然后输入描述文件名称,描述文件名称字符和数字,自己好辨识就可以。然后选择描述文件类型,再选择bundle ID,如果…...
进行性能压力测试的原因、目的和好处
性能压力测试是指在模拟高负载、高并发情况下对软件系统进行测试,以衡量系统在实际使用过程中的性能表现。这些测试可以为生产环境中的应用程序提供关键数据,并帮助开发人员从根本上了解系统的实际性能。在本文中,我们将探讨进行性能压力测试…...
【计算机视觉】如何利用 CLIP 做简单的人脸任务?(含源代码)
文章目录 一、数据集介绍二、源代码 结果三、代码逐行解读 一、数据集介绍 CELEBA 数据集(CelebFaces Attributes Dataset)是一个大规模的人脸图像数据集,旨在用于训练和评估人脸相关的计算机视觉模型。该数据集由众多名人的脸部图像组成&a…...
基于显扬科技3D视觉相机的医疗试管分拣系统
行业现状: 医疗试管分拣是医疗行业中的一个重要环节,指将医疗实验室或生物技术研究中的试管按照一定的规则进行分拣,并对试管的类型、位置、数量等信息进行识别和管理。 随着医疗技术的不断发展和诊断治疗的精细化,医疗试管分拣…...
编译zlib
zlib被设计为一个免费的,通用的,法律上不受限制的-即不受任何专利保护的无损数据压缩库,几乎可以在任何计算机硬件和操作系统上使用。 官网:http://www.zlib.net/ 下载zlib源码:http://www.zlib.net/zlib1213.zip 备用地址&#x…...
如何让“ChatGPT自己写出好的Prompt的“脚本在这里
写个好的Prompt太费力了 在网上,你可能会看到很多人告诉你如何写Prompt,需要遵循各种规则,扮演不同的角色,任务明确、要求详细,还需要不断迭代优化。写一个出色的Prompt需要投入大量的时间和精力。甚至有一些公开的Pr…...
菜单选择shell
[rootes3 data]# vi action.sh #!/bin/bash . /etc/init.d/functionsecho -en "\E[$[RANDOM%731];1m"cat <<EOF请选择:1) 备份数据库2)清理日志3)软件升级4)软件回滚5)删库跑路EOFecho -en \E[0mread -p "请选择上面的项对应的数字1-5…...
Redis高可用性详解
目录 编辑 高可用性: 主从复制(Master-Slave Replication): 主从复制的一般工作流程: 哨兵模式(Sentinel Mode): 哨兵模式的一般工作流程: 集群模式(…...
MySQL(1) ---- 数据库介绍与MySQL概述
介绍 1、什么是数据库? 数据库:DateBase(DB),是存储和管理数据的仓库。数据库管理系统:DataBase Management System(DBMS),操纵和管理数据库的大型软件。SQL࿱…...
面试题之软件测试流程
说说公司的软件测试流程,这,是常考的面试题之一。 不同公司的流程不一样,现状决定流程,没有绝对的对错。 以结果为导向,保证产品质量,提高测试效率,才是王道。 以下的流程为业界比较标准的流程&…...
MyBatis中#{}与${}的区别,与各自的应用场景
#{}和${}的区别: #{}: 底层使用PreparedStatement。特点:先进行SQL语句的编译,然后给SQL语句的占位符问号?传值。可以避免SQL注入的风险。 ${}:底层使用Statement。特点:先进行SQL语句的拼接,然后再对SQL语…...
泛型类相关
package com.test.test02;/* * GenericTest就是一个普通的类 * GenericTest<E>就是一个泛型类 * <>里面就是一个参数类型,但是这个类型是什么呢?这个类型现在是不确定的,相当于一个占位。 * 但是现在确定的是这个类型一定是一…...
一文速学数模-季节性时序预测SARIMA模型详解+Python实现
目录 前言 一、季节时间序列模型概述 二、SARIMA模型定义 三.SARIMA模型算法原理...
二叉树与图(C++刷题笔记)
二叉树与图(C刷题笔记) 113. 路径总和 II 力扣 从根节点深度遍历二叉树,先序遍历时,将节点存储至path栈中,使用path_val累加节点值 当遍历到叶子节点,检查path_val是否为sum,若是,…...
STM32-ADC多通道输入实验
之前已经介绍了几个ADC的笔记和实验了,链接如下: 关于ADC的笔记1_Mr_rustylake的博客-CSDN博客 STM32-ADC单通道采集实验_Mr_rustylake的博客-CSDN博客 STM32-单通道ADC采集(DMA读取)实验_Mr_rustylake的博客-CSDN博客 接下来…...
javaIO流之文件流
目录 简介一、File的构造方法二、File的常用方法1、获取功能的方法2、绝对路径和相对路径3、判断功能的方法4、创建、删除功能的方法5、目录的遍历6、递归遍历 三、RandomAccessFile1、主要方法 四、Apache FileUtils 类1、复制文件或目录:2、删除文件或目录&#x…...
ChanlunX缠论插件:3分钟掌握专业级K线分析,告别复杂缠论学习曲线!
ChanlunX缠论插件:3分钟掌握专业级K线分析,告别复杂缠论学习曲线! 【免费下载链接】ChanlunX 缠中说禅炒股缠论可视化插件 项目地址: https://gitcode.com/gh_mirrors/ch/ChanlunX 还在为复杂的缠论分析头疼吗?ChanlunX缠论…...
5分钟拯救珍贵视频!untrunc视频修复工具终极指南
5分钟拯救珍贵视频!untrunc视频修复工具终极指南 【免费下载链接】untrunc Restore a truncated mp4/mov. Improved version of ponchio/untrunc 项目地址: https://gitcode.com/gh_mirrors/un/untrunc 您是否曾因相机突然断电、存储卡故障或传输中断而丢失珍…...
保姆级教程:用Proteus 8.13和STM32F103C8T6复刻一个智能烟雾报警器(附源码)
从零构建基于STM32的智能烟雾报警系统:Proteus仿真与硬件实战指南 在电子设计领域,能够将虚拟仿真与实物开发无缝衔接的能力已成为工程师的核心竞争力。本文将带您完整走通从Proteus仿真到STM32硬件实现的智能烟雾报警系统开发全流程,特别适合…...
DecompilerMC:5分钟解锁Minecraft源码,模组开发者的终极神器
DecompilerMC:5分钟解锁Minecraft源码,模组开发者的终极神器 【免费下载链接】DecompilerMC This repository allows you to decompile any minecraft version that was published after 19w36a without any 3rd party mappings, you just need to execu…...
南北阁Nanbeige 4.1-3B入门必看:纯本地运行、无网依赖、4GB显存友好部署指南
南北阁Nanbeige 4.1-3B入门必看:纯本地运行、无网依赖、4GB显存友好部署指南 想体验一个能流畅对话、还能“看见”它思考过程的AI助手吗?今天要介绍的南北阁Nanbeige 4.1-3B,就是一个让你在普通电脑上就能跑起来的国产小模型。它只有30亿参数…...
【macOS】精选效率神器!大幅提升办公速度的宝藏软件
目录 01 文本编辑 1.1 Notable 1.2 MarkEdit01 文本编辑 1.1 Notable 🌸 开源轻量化 Markdown 笔记,主打数据可控。 🌸 支持多系统:Linux, Windows, macOS。 🌺 网址为:https://notable.app/ 1.2 MarkEdi…...
UPF3.0实战:5步搞定芯片低功耗设计中的电源域划分(附VCS仿真技巧)
UPF3.0实战:5步搞定芯片低功耗设计中的电源域划分(附VCS仿真技巧) 在数字IC设计领域,低功耗已成为衡量芯片竞争力的核心指标之一。随着工艺节点不断下探,静态功耗占比显著提升,传统的时钟门控技术已无法满足…...
分布式智能解析引擎:抖音视频批量下载的架构设计与性能优化指南
分布式智能解析引擎:抖音视频批量下载的架构设计与性能优化指南 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallb…...
3分钟免费安装GitHub中文插件:告别英文困扰,让开发效率翻倍![特殊字符]
3分钟免费安装GitHub中文插件:告别英文困扰,让开发效率翻倍!🚀 【免费下载链接】github-chinese GitHub 汉化插件,GitHub 中文化界面。 (GitHub Translation To Chinese) 项目地址: https://gitcode.com/gh_mirrors/…...
从单点通信到批量处理:s7netplus如何优化西门子PLC数据传输性能
从单点通信到批量处理:s7netplus如何优化西门子PLC数据传输性能 【免费下载链接】s7netplus S7.NET -- A .NET library to connect to Siemens Step7 devices 项目地址: https://gitcode.com/gh_mirrors/s7/s7netplus 在工业自动化系统中,PLC&…...
