简述 JavaScript 中 prototype

news2024/12/22 23:36:58

简述 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]] 的方法有两种:

  1. __proto__

    已经 Deprecated 了,deno 中甚至不支持实现

  2. 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 的作用在于

  1. 它创建了一个新的对象
  2. 它关联了对应的原型链继承
  3. 它绑定了 this 的指向
  4. 它执行了构造函数内的部分

一个简单的实现 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 了。

superthis

到这一步,基本上使用 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();

在这里插入图片描述

接下来要模拟实现的就是这一步,其中需要注意的就是:

  1. 实现继承关系

    这点可以通过修改 prototype 进行实现,已知 [[Prototype]] 中包含了所有的 prototype chain,这里也只需要将 Child.prototype 指向 Parent.prototype,并且绑定对应的 构造函数即可。

  2. 修改 this 的指向

function Parent() {
  this.name = 'Parent';
}

Parent.prototype.greet = function () {
  console.log(`This is ${this.name}`);
};

function Child() {
  // bind child to parent
  Parent.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 的代码更加简洁易读。

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

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

相关文章

linux(缓冲区学习)

目录&#xff1a; 1.对进程是如何和这个进程打开文件进行关联的总结 2.标准输出和标准错误都是往显示器上打印--有何区别 3.缓冲区 --------------------------------------------------------------------------------------------------------------------------- 1.对进程是…

双模齐下,提质增效:知微携手CODING共创BizDevOps体系新篇章

为了提升工作和管理效率&#xff0c;工具建设是许多企业不得不面对的现实&#xff0c;然而在工具建设落地过程中&#xff0c;往往存在一系列的问题。如不同组织、部门之间互不相通&#xff0c;各自为政&#xff0c;工具流程与实际工作所需不符&#xff0c;导致工具建设的结果是…

做实大模型的产业价值,度小满深耕“NLP+金融”

2023年的五月&#xff0c;称得上一句AI之夏。 大模型层出不穷、扎堆发布。 这一轮由大模型推动的AI热潮中&#xff0c; NLP&#xff08;自然语言处理&#xff09;技术与金融落地场景的结合备受期待。金融行业是数字化、智能化的先行者&#xff0c;也是大模型技术落地的最佳领域…

chatgpt赋能Python-python3h怎么操作

Python3 SEO操作指南 Python3语言已成为计算机编程领域的标准和主要工具之一。SEO&#xff08;Search Engine Optimization&#xff09;是一种促进网站在搜索引擎结果中排名的技术。Python3也可以用来执行SEO操作&#xff0c;本文将介绍如何使用Python3进行SEO操作&#xff0c…

替换字符串的关键字KeywordProcessor

【小白从小学Python、C、Java】 【等级考试500强双证书考研】 【Python-数据分析】 替换字符串的关键字 KeywordProcessor [太阳]选择题 以下说法错误的一项是&#xff1a; from flashtext import KeywordProcessor myKP KeywordProcessor() myKP.add_keyword(English, Math) …

别在碳排放问题上大搞双重标准!

* * * 原创&#xff1a;刘教链 * * * 隔夜比特币从26.5k一线奋力跃升&#xff0c;回升至27.5k一线。 最近美国有些人又要对比特币的碳排放搞双重标准了。说的是比特币挖矿烧掉了多少多少电力&#xff0c;折合多少多少碳排放&#xff0c;因此应当加征多少多少排放税&#xff0c…

springboot+java电影院售票订票选座推荐系统554c6

主页是注册&#xff0c;登录&#xff0c;搜索。 用户在注册之前可以进行搜索查询现在上映的和即将上映的影片信息&#xff0c;但是不能在线购票。购票需注册登录之后方可。 用户可以修改自己注册后的账户信息&#xff0c;注册成功后直接登录。退出网页后&#xff0c;取消登录信…

ChatGPT APP来了,还可以直接订阅Plus账号,操作流程都这篇里面

大家好&#xff0c;我是可夫小子&#xff0c;关注AIGC、读书和自媒体。解锁更多ChatGPT、AI绘画玩法。加&#xff1a;keeepdance&#xff0c;备注&#xff1a;chatgpt&#xff0c;拉你进群。 OpenAI宣布推出聊天机器人ChatGPT的APP&#xff0c;目前已上架苹果App Store&#xf…

三十八、流控效果、热点数据限流、熔断降级、push到配置中心nacos

1、流控效果 流控效果是指请求达到流控阈值时应该采取的措施&#xff0c;包括三种&#xff1a; 快速失败&#xff1a;达到阈值后&#xff0c;新的请求会被立即拒绝并抛出FlowException异常。是默认的处理方式。 warm up&#xff1a;预热模式&#xff0c;对超出阈值的请求同样是…

OpenAI的巨额捐款背后,马斯克到底捐了多少?

来源&#xff1a;Techcrunch 作者&#xff1a;Mark Harris 编译&#xff1a;巴比特 自 2018 年 2 月退出 OpenAI 董事会以来&#xff0c;埃隆马斯克&#xff08;Elon Musk&#xff09;一直对 OpenAI 深感失望&#xff0c;这已不是什么秘密&#xff0c;最终他在一封公开信中呼吁…

每日涨停个股增量加入股票池,持续跟踪走势!股票量化分析工具QTYX-V2.6.5

功能概述 目前A股市场的股票每天是有限制最大涨幅的&#xff0c;也就是涨停的概念。比如主板个股最大涨幅是10%&#xff0c;创业板个股最大涨幅是20%等。 对于个股而言并不是随随便便就能被推到涨停板的。或是因为股票发生了重大的利好&#xff08;资产重组、政策利好、业绩暴增…

【Linux】——常见指令及权限理解

文章目录 1. 前言2. 用户管理3. 常见基本指令3.1 ls指令3.2 pwd指令3.3 cd指令3.4 touch指令3.5 mkdir指令3.6 rmdir指令和rm指令3.7 man指令3.8 cp指令3.9 mv指令3.10 cat指令3.11 more指令3.12 less指令3.13 head指令3.14 tail指令3.15 时间相关的指令3.16 cal指令3.17 find指…

价格战一触即发!阿里云、腾讯云、移动云“先降为敬”

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 5月16日&#xff0c;中国第三大云计算厂商腾讯云&#xff0c;宣布对多款核心云产品降价&#xff1b;随后&#xff0c;移动云也宣布了对多款云产品降价。如今&#xff0c;已有三家云厂商对产品进行降价。开第一枪的便是市场份…

MoJo:比Python快35000倍的全新编程语言!

大家注意&#xff1a;因为微信最近又改了推送机制&#xff0c;经常有小伙伴说错过了之前被删的文章&#xff0c;比如前阵子冒着风险写的爬虫&#xff0c;再比如一些限时福利&#xff0c;错过了就是错过了。 所以建议大家加个星标&#xff0c;就能第一时间收到推送。&#x1f44…

炼丹师,这是你的梦中情炉吗?

一, 炼丹之痛 无论是学术研究还是工业落地&#xff0c;pytorch几乎都是目前炼丹的首选框架。 pytorch的胜出不仅在于其简洁一致的api设计&#xff0c;更在于其生态中丰富和强大的模型库。 但是我们会发现不同的pytorch模型库提供的训练和验证代码非常不一样。 torchvision官方…

社区供稿 | 中文 LangChain 项目的实现开源工作

Chinese-LangChain 是 yanqiangmiffy 同学的开源项目https://hf.co/spaces/ChallengeHub/Chinese-LangChainhttps://github.com/yanqiangmiffy/Chinese-LangChain 中文 langchain 项目&#xff0c;基于 ChatGLM-6b langchain 实现本地化知识库检索与智能答案生成。 LangChain …

YOLOv5+姿态估计HRnet与SimDR检测视频中的人体关键点

一、前言 由于工程项目中需要对视频中的person进行关键点检测&#xff0c;我测试各个算法后&#xff0c;并没有采用比较应用化成熟的Openpose&#xff0c;决定采用检测精度更高的HRnet系列。但是由于官方给的算法只能测试数据集&#xff0c;需要自己根据算法模型编写实例化代码…

[网络安全]XSS之Cookie外带攻击姿势及例题详析

[网络安全]XSS之Cookie外带攻击姿势及例题详析 概念姿势及Payload启动HTTP协议 method1启动HTTP协议 method2 例题详析Payload1Payload2window.open 总结 本文仅分享XSS攻击知识&#xff0c;不承担任何法律责任。 本文涉及的软件等请读者自行安装&#xff0c;本文不再赘述。 概…

Node.js 学习系列(五)—— 文件系统

Node.js 提供一组类似 UNIX&#xff08;POSIX&#xff09; 标准的文件操作API。 Node 导入文件系统模块 (fs) 语法如下所示&#xff1a; var fs require("fs")异步和同步 Node.js 文件系统&#xff08;fs 模块&#xff09;模块中的方法均有异步和同步版本。 读取文…

异常体系与项目实践

程序式阴影&#xff1a;为什么不报错&#xff1f; 一、简介 在程序开发的过程中&#xff0c;异常处理从来都是一个复杂的维度&#xff0c;无论是新手还是经验老到的选手&#xff0c;在编码时都会面对各种异常情况&#xff1b; 程序中的异常可以反映系统的缺陷和待优化的点&am…