js原型和类---prototype,__proto__,new,class

news2024/10/2 20:30:49

原型和原型链

在js中,所有的变量都有原型,原型也可以有原型原型最终都指向Object

什么是原型

在js中,一个变量被创建出来,它就会被绑定一个原型;比如说,任何一个变量都可以使用console.log打印,这里是调用了它的toString方法,而变量被创建后可能并没有设置toString方法,但是它任然可以打印,这就从原型中获取的toString方法

 所以可以得到第一点:原型可以提供方法给实例的变量,

原型也是一个对象,或者说对象可以作为原型并赋值给其他变量,这样对象成为了变量的原型,而对象本身也有原型,此时就形成了 ‘链’

同样的这个变量也是一个对象,他也可以作为其他变量的原型,这样‘链’就变得更长了,但是所有的链都有一个最终指向(root终点)--- Object,Obejct是最原始的对象,它包含了所有js变量都共享的方法,它不再有原型属性[[prototype]], 所以在js中一切皆对象中的对象就是指的继承自Object

这里可以总结一下:

  • 原型是一个对象,它可以向继承了自身的变量提供方法(属性)
  • 变量都拥有原型,也可以成为原型,循环下去可以形成‘链’,
  • 链的最顶端是Object对象,它提供了最基本的方法

js通过原型来复用通用的方法和属性,这样极大的减少了变量创建的成本(减少了内存支出,原型的方法属性都存储在原型上,变量中不会复制过来占用内存;也不必每个对象都去书写基本的方法),

tips:

原型链:就前面说到的 变量获得原型,原型又有原型,变量又可以作为原型,这样就形成了‘链’,链的最外层(底层),拥有最多的方法,继承了原型链上所有原型的方法和属性

prototype

在 JavaScript 中,对象有一个特殊的隐藏属性 [[Prototype]](如规范中所命名的),它要么为 null,要么就是对另一个对象的引用。当我们从 object 中读取一个缺失的属性时,JavaScript 会自动从原型中获取该属性。这就是继承,object也可以从中借用方法

prototype不能在变量中被直接引用,通常没有办法遍历或者读取这个属性,所以它在控制台的名称有些特殊,使用[[ ]]引用,但是可以直接去调用它里面的方法,当你使用变量中不存在的属性或者方法,此时会自动向原型中寻找,对应的属性方法并调用,若原型链中没有则返回undefined

但是也有特例,在构造函数中,可以给构造的实例添加原型属性或方法

__proto__

这是一个过时的属性,现在只能在浏览器中使用,它的作用就是指向prototype,给原型添加属性或方法,这样添加的原型属性或方法会被遍历出来(Object.keys,for in),

let animal = {
  eats: true
};
let rabbit = {
  jumps: true
};

rabbit.__proto__ = animal; // 设置 rabbit.[[Prototype]] = animal

注意__proto__ 与内部的 [[Prototype]] 不一样__proto__ 是 [[Prototype]] 的getter/setter;获取和设置原型可以使用函数 Object.getPrototypeOf/Object.setPrototypeOf 来替代 __proto__ 去 get/set 原型

new

当使用 new 关键字调用函数时,该函数将被用作构造函数。new 将执行以下操作:

  1. 创建一个空的简单 JavaScript 对象作为实例。
  2. 如果构造函数的 prototype 属性是一个对象,则将实例的 原型[[Prototype]] 指向构造函数的 prototype 属性,否则实例将保持为一个普通对象,其 [[Prototype]]为 Object.prototype, 因此,通过构造函数创建的所有实例都可以访问添加到构造函数 prototype 属性中的属性/对象。
  3. 使用给定参数执行构造函数,并将this指向实例
  4. 如果构造函数返回非原始值,则该返回值成为整个 new 表达式的结果。否则,如果构造函数未返回任何值或返回了一个原始值,则返回实例。(通常构造函数不返回值,但可以选择返回值,以覆盖正常的对象创建过程。)

 new的关键点在于,它新建了一个实例对象,同时引入了原型,改变了构造函数的this指向,让实例对象成为了这个构造函数的构造结果

class

class是es6新增的语法糖,它简化了js中构造类的步骤,隐去了对原型的操作(根本上还是原型的操作),js中的类是基于原型的,使用原型达到继承的效果,

以下使用原型prototype和类class构建一个相同的类,

prototype.js

// 使用原型构造一个P类

// 构造器,大写开头规范(不强制)
function P (x,y){
  // this指向实例,此时this不生效,构造实例后指向实例
  this.x = x;
  this.y = y;
  // 实例方法,此处的this指向实例,可以使用实例的属性
  this.getXY = ()=>{
    return [this.x,this.y]
  }
}

// 实例方法,此处的this指向windows,不能使用实例的属性
P.prototype.getPName = ()=>{
  return P.name
}

// 实例属性
P.prototype.desc = '2维坐标'

//类方法/静态方法 
P.getP = (p1,p2)=>{
  return [p1.getXY(),p2.getXY()]
}

// 类属性/静态属性
P.des = '坐标'

class.js 

// 使用class构造一个P类

class P{
  //构造器
  constructor(x,y){
    this.x = x;
    this.y = y;
  }

  // 实例属性
  desc = '2维坐标'

  // 实例方法
  getXY(){
    return [this.x,this.y]
  }
  getPName(){
    return P.name
  }

  // 静态属性
  static des = '坐标'

  // 静态方法
  static getP(p1,p2){
    return [p1.getXY(),p2.getXY()]
  }
  
}

很明显,class的用法更加整体化,但实际上这两种的写法效果是完成相同的,

可以使用同一串代码来实例化这个类P

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>prototype,class</title>
</head>

<body>
  <script src="class.js"></script>
  <!-- <script src="prototype.js"></script> -->
  <script>
    // new关键字,新建一个对象,原型指向类,获得构造器中的this指向
    let p = new P(1, 2);
    console.log(p);
    console.log(p.x);
    console.log(p.y);
    console.log(p.desc);
    console.log(p.getXY());
    console.log(p.getPName());
    console.log(P.getP(p, p));
    console.log(P.des);
  </script>
</body>

</html>

实现的效果是一致的方法上略有不同,对于类的构造,关键在于this的指向问题,属性和方法是挂在类名下的,还是挂在实例下的需要区分开,

挂在类下的属性方法被称为,类方法(属性)或者静态方法(属性),通过类名引用(Math.max)

挂在实例下的属性方法被称为,实例方法(属性),通过实例引用(arr.push)

总结

  • 在 JavaScript 中,所有的对象都有一个隐藏的 [[Prototype]] 属性,它要么是另一个对象,要么就是 null
  • 通过 [[Prototype]] 引用的对象被称为“原型”。
  • "prototype" 属性仅当设置在一个构造函数上,并通过 new 调用时,才具有这种特殊的影响。在常规对象上,prototype 会被当成是一个普通的属性名
  • 所以变量都通过原型/原型链使用共享的方法(即自身不存在,从原型/原型链中借用)
  • 类的使用要区分实例和静态类,哪些方法属性在类名下,哪些方法属性在实例下

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

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

相关文章

数据结构 Java DS——链表部分经典题目 (1)

前言 笔者计划在暑假啃完JavaDS,Mysql的内容当然也会继续更 这次给读者们分享的是链表的几个比较典型的题目,关于如何手搓一个链表,笔者还在筹划中, 毕竟链表的种类也有那么多,但是在下面的题目中,只有单向链表 题目一 : 反转链表 206. 反转链表 - 力扣&#xff08;LeetCode…

文献笔记|综述|When Large Language Model Meets Optimization

When Large Language Model Meets Optimization 题目&#xff1a;当大型语言模型遇到优化时 作者&#xff1a;Sen Huang , Kaixiang Yang , Sheng Qi and Rui Wang 来源&#xff1a;arXiv 单位&#xff1a;华南理工大学 文章目录 When Large Language Model Meets Optimization…

java:字符缓冲流特有功能

BufferedWriter&#xff1a; void newLine&#xff08;&#xff09;&#xff1a;写一行行分隔符&#xff0c;行分隔符字符串由系统属性定义 BufferedReader&#xff1a; public String readLine&#xff08;&#xff09;&#xff1a;读一行文字&#xff0c;结果包含行的内容的字…

Mosh|初学者 SQL 教程

sql文件链接&#xff1a;链接: https://pan.baidu.com/s/1okjsgssdxMkfKf8FEos7DA?pwdf9a9 提取码: f9a9 在mysql workbench 导入 create_databases.sql 文件&#xff0c;下面是运行成功的界面 快捷方式&#xff1a;全部运行可以同时按下controlcommandenter &#xff0c;或者…

rsync远程同步--累了,明天继续再写~。

rsync官网链接 rsync(Remote Sync,远程同步)开源快速备份工具&#xff0c;是一个用于本地和远程文件同步的Unix-like命令行程序。它使用“快速数据传输算法”&#xff0c;只发送源和目标之间的差异&#xff0c;因此数据传输非常高效。 可以在不同主机之间镜像同步整 个目录树…

基于网络编码的 tcp 变种-tcp/nc

tcp/nc 是指 “tcp with network coding”&#xff0c;是一种结合了网络编码技术的 tcp 变种&#xff0c;网上资源很少&#xff0c;我也不准备多介绍&#xff0c;只介绍它的核心。 传统 tcp 在演进过程中一直搞不定效率问题&#xff0c;网络带宽在增长&#xff0c;cpu 却没有变…

Python学习中使用循环(for, while)

在Python编程语言中&#xff0c;循环是一个非常重要的概念&#xff0c;可以帮助我们在代码中重复执行某些操作。Python支持两种主要的循环结构&#xff1a;for 循环和 while 循环。 1. for 循环 for 循环用于遍历一个序列&#xff08;如列表、元组、字符串&#xff09;或其他…

自动化数据集成的BI工具,为你提供决策洞察力

传统的商业智能&#xff08;BI&#xff09;报表系统采用的是“业务提报表需求&#xff0c;IT进行开发”的模式。决策管理者和业务人员提出用报表等来展示经营管理数据的需求&#xff1b;接着IT响应需求&#xff0c;进行需求沟通、数据处理加工、报表开发等主体工作&#xff1b;…

南方科技大学马永胜教授给年轻人使用AI工具上的建议

摘要 - 1. AI的未来&#xff0c;是机器人和机器人之间的合作&#xff1b; 2. 行业的发展方向是需求决定的&#xff0c;不要做同质化的发展&#xff0c;要做专/精/特/新&#xff1b; 3. 新质生产力 &#xff08; 科学技术革命性突破 生产要素创新型配置 产业深度转型升级&…

Text Control 控件教程:在 .NET 中打印 MS Word DOCX 文档

虽然有用于创建 DOCX 文件的库&#xff08;例如 Open XML SDK&#xff09;&#xff0c;但打印又是另一回事。打印 DOCX 文件的唯一方法是在 Microsoft Word 中打开它并手动打印。对于需要打印大量文档的 Web 应用程序或需要自动打印文档的服务器端应用程序来说&#xff0c;这不…

CSS相对定位和绝对定位的区别

CSS相对定位和绝对定位的区别 区别1&#xff1a;相对的对象不同 相对定位是相对于自己绝对定位是相对于离自己最近的有定位的祖先 区别2:是否会脱离文档流 相对定位不会脱离文档流&#xff0c;不会影响其他元素的位置绝对定位会脱离文档流&#xff0c;会影响其他元素的布局 代…

人与机器的协同是强弱系统的互补行为

人与机器的协同可以被视作强弱系统的互补行为&#xff0c;这也强调了人类和机器之间在处理问题、执行任务或创造价值时各自的优势与角色。 人类在认知、创造力、情感和伦理等方面具有独特优势。我们能够进行高级的抽象思维、创新和复杂决策&#xff0c;能够处理不确定性和动态环…

realloc调整栈帧

同样的&#xff0c;也仅仅是记录自己学习的记录、思考。 优秀的学习文章 使用realloc函数来调整栈帧让one_gadget生效 | ZIKH26 调试分析 one_gadget失效 这种都需要自己动手调试来看 以经典的libc-2.23的fastbin attack为例 one_gadget libc-2.23.so edit(2,8,p64(mall…

怎样在 PostgreSQL 中优化对大数值类型数据的计算?

文章目录 一、选择合适的数据类型二、索引优化三、查询语句优化四、数据库配置调整五、使用扩展功能六、示例七、总结 在 PostgreSQL 中处理大数值类型数据&#xff08;例如 BIGINT、NUMERIC 等&#xff09;的计算时&#xff0c;可能会遇到性能瓶颈。为了优化这些计算&#xff…

coze搭建工作流和Agent

coze搭建工作流和Agent Agent LLM 记忆感知规划使用工具 LLM是大语言模型&#xff0c;prompt提示词影响LLM的输出质量 描述需求——>背景——>解决思路&#xff0c;提示词文档。 当有明确的需求和实现需求的路径时&#xff0c;可以通过搭建工作流来完成标准化任务为…

从零开始学习嵌入式----Linux系统命令集合与shell脚本

Shell是一门编程语言&#xff0c;作为学习shell的开始&#xff0c;需要事先搞明白&#xff1a;编程的目的是什么&#xff1f;什么是编程语言&#xff1f;什么是编程&#xff1f; shell本身就是一门解释型、弱类型、动态语言&#xff0c;与python相对应&#xff0c;Python属于解…

办公室卫生间厕位引导牌款式多样,都有哪些功能

在现代办公环境中&#xff0c;卫生间不仅是员工日常使用的必需设施&#xff0c;也是体现企业文化和管理水平的一面镜子。然而&#xff0c;传统办公室卫生间往往存在着信息不透明、高峰期拥挤、清洁维护滞后等问题&#xff0c;影响了员工的使用体验。近年来&#xff0c;随着智慧…

0基础学会在亚马逊云科技AWS上搭建生成式AI云原生Serverless问答QA机器人(含代码和步骤)

小李哥今天带大家继续学习在国际主流云计算平台亚马逊云科技AWS上开发生成式AI软件应用方案。上一篇文章我们为大家介绍了&#xff0c;如何在亚马逊云科技上利用Amazon SageMaker搭建、部署和测试开源模型Llama 7B。下面我将会带大家探索如何搭建高扩展性、高可用的完全托管云原…

个人标准流程管理系统

个人标准流程管理系统&#xff08;Personal Standard Operating Procedure System, PSOPS&#xff09;是一种帮助个人组织和优化日常任务、项目管理、学习计划和其他重复性活动的工具。它旨在提升个人效率&#xff0c;确保各项事务按照预设的标准流程执行。以下是设计这样一个系…

PPI(每英寸像素数)、DPI(每英寸点数)和Pixel(像素)的区别和联系?

一、定义 PPI、DPI和Pixel是图像处理、打印和显示领域中常用的三个概念&#xff0c;它们之间既有区别又有联系。以下是对这三个概念进行分别讲解&#xff1a; 1. PPI&#xff08;Pixels Per Inch&#xff09;&#xff0d;即每英寸像素数&#xff0c;是图像分辨率的一种表示方…