揭秘原型链:探索 JavaScript 面向对象编程的核心(下)

news2025/6/7 11:30:05

在这里插入图片描述

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6
🍨 阿珊和她的猫_CSDN个人主页
🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》
🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入门到实战全面掌握 uni-app》

文章目录

  • 五、使用原型链的注意事项
    • 原型链的性能考虑
    • 避免循环引用
  • 六、常见的原型链问题及解决方法
    • 原型链污染
  • 七、优化原型链的技巧
    • 使用构造函数模式
  • 八、总结
    • 原型链的重要性和应用场景
    • 优化原型链的方法

五、使用原型链的注意事项

原型链的性能考虑

原型链在 JavaScript 中是一种强大而灵活的机制,用于实现继承、共享属性和方法等功能。然而,在考虑原型链的性能时,需要注意以下几点:
在这里插入图片描述

  1. 查找速度:原型链的查找速度相对较慢,因为它需要沿着链进行多次查找才能找到所需的属性或方法。在大型的对象结构中,这种查找可能会导致一定的性能开销。

  2. 共享属性:原型链中的属性是共享的,这意味着如果多个对象共享同一个原型对象,对其中一个对象的属性修改可能会影响到其他对象。这在某些情况下可能会导致意外的行为,需要谨慎处理。

  3. 内存占用:由于原型链中的对象是引用类型,它们在内存中只存在一个实例。这可以减少内存的使用,但也可能导致内存泄漏的风险。如果一个原型对象被大量对象引用,并且不再被使用,它可能会一直存在于内存中,直到整个 JavaScript 运行环境被释放。

为了优化原型链的性能,可以考虑以下几点:

  1. 尽量减少原型链的长度:通过合理的类设计和继承层次结构,尽量减少原型链的长度,以提高属性和方法的查找速度。

  2. 使用优化的方法:对于频繁访问的属性和方法,可以考虑将它们直接定义在对象本身,而不是通过原型链来访问。这样可以提高访问速度。

  3. 避免共享敏感属性:如果需要在对象之间保持独立的状态,尽量避免在原型对象上定义敏感属性,以避免意外的修改影响到其他对象。

  4. 注意内存泄漏:在处理不再使用的原型对象时,及时释放对它们的引用,以避免内存泄漏的问题。

在这里插入图片描述

总的来说,原型链在 JavaScript 中是一种强大而灵活的机制,但在考虑性能时需要谨慎处理。通过合理的设计和优化,可以在保持原型链的优势的同时,最大程度地减少性能问题。

避免循环引用

在 JavaScript 中,循环引用是指两个或多个对象之间相互引用,形成一个循环的引用关系。
这种情况可能会导致内存泄漏,因为这些对象将无法被垃圾回收器正确释放。

为了避免循环引用,可以采取以下措施:

  1. 解除引用:在不再需要对象时,及时将对它们的引用解除,以确保它们可以被垃圾回收器正确释放。可以使用 nullundefined 来赋值给对象的引用,以解除引用。

  2. 使用 weakMap:WeakMap 是 JavaScript 中的一种弱引用数据结构,它允许存储对象作为键,但不会阻止这些对象被垃圾回收器回收。可以使用 WeakMap 来存储对对象的弱引用,从而避免循环引用。

  3. 使用 Proxy 对象:Proxy 对象可以用来创建一个代理对象,该代理对象可以拦截对另一个对象的访问。通过使用 Proxy 对象,可以在访问对象的属性时进行特殊处理,例如自动解除引用,从而避免循环引用。

在这里插入图片描述

以下是一个示例,展示如何使用 WeakMap 来避免循环引用:

class MyClass {
  constructor() {
    this.myWeakMap = new WeakMap();
  }

  setReference(obj) {
    this.myWeakMap.set(obj, true);
  }

  clearReference(obj) {
    this.myWeakMap.delete(obj);
  }
}

const obj1 = new MyClass();
const obj2 = new MyClass();

obj1.setReference(obj2);
obj2.setReference(obj1);

// 释放引用
obj1.clearReference(obj2);
obj2.clearReference(obj1);

// 现在 obj1 和 obj2 可以被正确回收

在这个示例中,MyClass 类使用 WeakMap 来存储对其他对象的弱引用。通过使用 setReference 方法来设置弱引用,并使用 clearReference 方法来清除弱引用,可以避免循环引用导致的内存泄漏问题。

需要注意的是,WeakMap 只能存储对象作为键,而不能存储基本类型的值。此外,WeakMap 的键是弱引用的,这意味着如果没有其他强引用指向这些键,它们将被垃圾回收器回收。

总的来说,避免循环引用是确保 JavaScript 应用程序内存安全的重要方面。通过及时解除引用、使用 WeakMap 或其他适当的技术,可以有效地避免循环引用导致的内存泄漏问题。

六、常见的原型链问题及解决方法

原型链污染

原型链污染是指在原型链上意外地修改了对象的原型,导致其他对象受到影响。这可能会导致不可预测的行为和错误。

以下是一个可能导致原型链污染的示例:

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.friends = ["John", "Jane"];

function Employee(salary) {
  Person.call(this, "John", 30);
  this.salary = salary;
}

Employee.prototype = Object.create(Person.prototype);

const employee = new Employee(5000);

// 意外地修改了原型链
employee.friends.push("Bob");

console.log(employee.friends); // 输出: ["John", "Jane", "Bob"]
console.log(new Person().friends); // 输出: ["John", "Jane", "Bob"]

在这个示例中,我们创建了一个 Person 类和一个继承自 PersonEmployee 类。我们将 Employee 的原型对象设置为 Person 的原型对象的一个副本,以实现继承。

然而,在后面的代码中,我们意外地修改了 employee 对象的 friends 属性,这导致了原型链的污染。由于 Employee 的原型对象是 Person 的原型对象的副本,所以对 employee.friends 的修改也会反映在 Person 的原型对象上。

为了避免这种问题,可以采取以下措施:

  1. 避免直接修改原型对象:尽量避免直接修改原型对象上的属性。如果需要在对象之间共享属性或方法,可以考虑使用构造函数或其他合适的模式。

  2. 使用 Object.assign()... 扩展运算符:在创建子类时,可以使用 Object.assign()... 扩展运算符来复制父类的属性,而不是直接使用原型链。

  3. 使用 Object.preventExtensions():可以使用 Object.preventExtensions() 方法来防止对象的属性被意外修改。这可以在创建对象后立即调用,以确保对象的属性不会被意外修改。

以下是一个使用 Object.preventExtensions() 来避免原型链污染的示例:

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.friends = ["John", "Jane"];

function Employee(salary) {
  Person.call(this, "John", 30);
  this.salary = salary;
}

Employee.prototype = Object.create(Person.prototype);

const employee = new Employee(5000);

// 使用 Object.preventExtensions() 防止属性被意外修改
Object.preventExtensions(employee);

employee.friends.push("Bob");

console.log(employee.friends); // 输出: ["John", "Jane"]
console.log(new Person().friends); // 输出: ["John", "Jane"]

在这个示例中,我们使用 Object.preventExtensions() 方法来防止 employee 对象的属性被意外修改。这样,即使我们尝试修改 employee.friends,也不会影响到 Person 的原型对象。

需要注意的是,使用 Object.preventExtensions() 方法会使对象变得不可扩展,无法添加新的属性。如果需要在对象上添加新的属性,可以考虑使用其他方法,例如使用 Object.defineProperty() 或使用其他合适的数据结构。

七、优化原型链的技巧

使用构造函数模式

在 JavaScript 中,优化原型链的一种常见技巧是使用构造函数模式(Constructor Pattern)。构造函数模式通过使用构造函数来创建对象,并在构造函数中定义对象的属性和方法。这种模式可以避免使用原型链来共享属性和方法,从而提高性能和可维护性。

以下是一个使用构造函数模式的示例:

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.friends = ["John", "Jane"];

function Employee(salary) {
  Person.call(this, "John", 30);
  this.salary = salary;
}

Employee.prototype = Object.create(Person.prototype);

const employee = new Employee(5000);

employee.friends.push("Bob");

console.log(employee.friends); // 输出: ["John", "Jane", "Bob"]
console.log(new Person().friends); // 输出: ["John", "Jane"]

在这个示例中,我们创建了一个 Person 类和一个继承自 PersonEmployee 类。我们使用 Object.create() 方法来创建 Employee 的原型对象,并将其设置为 Person 的原型对象的一个副本。

这样,Employee 就可以继承 Person 的属性和方法,包括共享的 friends 属性。由于 Employee 的原型对象是 Person 的原型对象的副本,所以对 employee.friends 的修改不会影响到 Person 的原型对象。

这种模式可以提高性能和可维护性,因为它避免了在原型链上进行多次查找和修改,并且可以更好地控制对象的属性和方法。但是,在某些情况下,使用原型链来共享属性和方法可能更加方便和灵活,具体取决于您的需求和使用场景。

八、总结

原型链的重要性和应用场景

原型链是 JavaScript 中一个重要的概念,它允许对象通过原型链来共享属性和方法,从而提高代码的灵活性和可复用性。以下是原型链的重要性和一些常见的应用场景:

重要性:

  1. 代码复用:原型链允许对象通过继承来共享属性和方法,从而减少了代码的重复。
  2. 动态扩展:原型链允许在运行时动态地向对象添加属性和方法,从而提高了代码的灵活性。
  3. 提高性能:原型链可以减少对象的创建,因为对象可以通过原型链来共享属性和方法,从而提高了性能。
    在这里插入图片描述

应用场景:

  1. 继承:原型链是 JavaScript 中实现继承的一种方式。通过将一个对象的原型设置为另一个对象的实例,可以实现继承。
  2. 共享属性和方法:原型链允许对象通过原型链来共享属性和方法,从而减少了代码的重复。
  3. 扩展对象:原型链允许在运行时动态地向对象添加属性和方法,从而提高了代码的灵活性。
  4. 原型污染:原型链可能会导致原型污染,即在原型链上意外地修改了对象的原型。为了避免这种情况,可以使用构造函数模式或类模式来创建对象。
    在这里插入图片描述

总之,原型链是 JavaScript 中一个重要的概念,它允许对象通过原型链来共享属性和方法,从而提高了代码的灵活性和可复用性。在使用原型链时,需要注意避免原型污染,并根据具体的应用场景选择合适的方法来创建对象。

优化原型链的方法

以下是优化原型链的一些方法:

  1. 使用构造函数模式:通过使用构造函数来创建对象,并在构造函数中定义对象的属性和方法。这种模式可以避免使用原型链来共享属性和方法,从而提高性能和可维护性。
  2. 使用类模式:类模式是一种更高级的构造函数模式,它使用 class 关键字来定义类,并使用 extends 关键字来实现继承。类模式提供了更好的语法糖和类型检查,可以提高代码的可读性和可维护性。
  3. 避免直接修改原型对象:尽量避免直接修改原型对象上的属性。如果需要在对象之间共享属性或方法,可以考虑使用构造函数或其他合适的模式。
  4. 使用 Object.preventExtensions():可以使用 Object.preventExtensions() 方法来防止对象的属性被意外修改。这可以在创建对象后立即调用,以确保对象的属性不会被意外修改。
  5. 使用 Object.defineProperty():可以使用 Object.defineProperty() 方法来定义对象的属性,并设置其可枚举性、可写性和可配置性。这可以提高代码的可读性和可维护性,并避免潜在的问题。

在这里插入图片描述

这些方法可以帮助优化原型链,提高代码的性能和可维护性。具体的优化方法应根据具体的应用场景和需求来选择。

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

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

相关文章

Swin Transformer实战图像分类(Windows下,无需用到Conda,亲测有效)

目录 前言 一、从官网拿到源码,然后配置自己缺少的环境。 针对可能遇到的错误: 二、数据集获取与处理 2.1 数据集下载 2.2 数据集处理 三、下载预训练权重 四、修改部分参数配置 4.1 修改config.py 4.2 修改build.py 4.3 修改units.py 4.4 修…

【程序设计】简易生产者、消费者模型

需求: 创建消息队列时需要指定队列的容量上限,队列中没有消息时,消费者从队列中take元素会阻塞;队列中的消息数量达到容量上限时,生产者往队列中put元素会阻塞。要保证线程安全。 组成: (1&…

西南科技大学模拟电子技术实验五(集成运算放大器的应用设计)预习报告

一、计算/设计过程 设计一:用集成运放设计一个输入为0.05v,放大为-100的反相比例运算电路。 对于理想电路,反相比例运算电路的输出电压与输入电压之间的关系如下: =-100,所以 =100 若是假定R1为100k,则R2= =1k 为了减小输入级偏置电流引起的运算误差,在同相输入端…

全新MacOS固件正式版发布,打造出色的操作系统体验!

MacOS 11-14(PKG系统安装包及IPSW固件) 11.7.10/12.7.1/13.6.2/14.1.2正式版已经隆重发布!这些固件版本适用于MacOS 11至14,带来了令人瞩目的升级和改进。 新版本固件通过增强系统的稳定性和性能,为用户创造了更加出色的操作系统体验。无论您…

VSC++: string声明的字符串这么相加

缘由https://bbs.csdn.net/topics/397667834 void string声明的字符串这么相加() {//缘由https://bbs.csdn.net/topics/397667834struct teacher { string name; };teacher t[3];string teachernameseed1 "张赵王";//把字符串放入种子中string teachernameseed2 &…

Docker从入门到实战:Docker快速部署、Dockerfile编写、容器间通信及共享数据实战、Docker-compose详解

文章目录 一、基本概念1、体系结构2、容器与镜像1&#xff09;镜像2&#xff09;容器a、容器内部结构b、容器生命周期 3、执行流程 二、常用命令docker pull 镜像名<:tags> &#xff1a;从远程仓库抽取镜像docker images&#xff1a;查看本地镜像docker run 镜像名<:t…

vue项目node-sass^4.14.1 python gyp 报错解决办法

npm i node-sass4.14.1 --sass_binary_sitehttps://npm.taobao.org/mirrors/node-sass/参考链接&#xff1a;链接

wireshark自定义协议插件开发

目录 脚本代码 报文显示 脚本代码 local NAME "test" test_proto Proto("test", "test Protocol") task_id ProtoField.uint16("test.task_id", "test id", base.DEC) cn ProtoField.uint8("test.cn", &qu…

ganache部署智能合约报错VM Exception while processing transaction: invalid opcode

这是因为编译的字节码不正确&#xff0c;ganache和remix编译时需要选择相同的evm version 如下图所示&#xff1a; remix: ganache: 确保两者都选择london或者其他evm&#xff0c;只要确保EVM一致就可以正确编译并部署&#xff0c; 不会再出现VM Exception while processing…

组合模式-C++实现

组合模式是一种结构型设计模式&#xff0c;它允许我们将对象组织成树状结构&#xff0c;并以递归的方式处理它们。该模式通过将单个对象和组合对象统一对待&#xff0c;使得客户端可以以一致的方式处理对象集合。 组合模式中有两种角色&#xff1a;组合和组件。组件就是叶子节…

三轴加速度计LIS2DW12开发(2)----基于中断信号获取加速度数据

三轴加速度计LIS2DW12开发.2--轮基于中断信号获取加速度数据 概述视频教学样品申请生成STM32CUBEMX串口配置IIC配置CS和SA0设置INT1设置串口重定向参考程序初始换管脚获取ID复位操作BDU设置开启INT1中断设置传感器的量程配置过滤器链配置电源模式设置输出数据速率中断判断加速…

常用数据预处理方法 python

常用数据预处理方法 数据清洗缺失值处理示例删除缺失值插值法填充缺失值 异常值处理示例删除异常值替换异常值 数据类型转换示例数据类型转换在数据清洗过程中非常常见 重复值处理示例处理重复值是数据清洗的重要步骤 数据转换示例 数据集成示例数据集成是将多个数据源合并为一…

基于Intel Ai Analytics Toolkit 及边缘计算的溶氧预测水产养殖监测方案

基于AI的淡水养殖水质溯源、优化系统方案 前言一、关键需求及方案概述二、方案设计预测机制LSTM 模型基于intel AI 的时序水质分析模型与分类模型优化 三、实战分析1、方案简述2、数据分析预处理特征类型处理特征分布分析 3、特征构造4、特征选择过滤法重要性排序 5.构建LSTM模…

Android drawable layer-list右上角红点,xml布局实现,Kotlin

Android drawable layer-list右上角红点&#xff0c;xml布局实现&#xff0c;Kotlin <?xml version"1.0" encoding"utf-8"?> <layer-list xmlns:android"http://schemas.android.com/apk/res/android"><itemandroid:id"id…

mfc项目设置软件版本

//上面设置的版本通过下面的代码可以获取到 TSTRING CVersion::GetSoftVersion() {TSTRING strVer _T("");TCHAR szPath[MAX_PATH] _T("");memset(szPath, 0, sizeof(szPath));::GetModuleFileName(NULL, szPath, sizeof(szPath));//得到本程序的目录UIN…

品优购:主体页,列表页,注册页

目录 main部分 recom推荐部分 新建列表list.html和list.css 创建register.html 和register.css main部分 focus焦点图通过ul和li框住img&#xff0c;右侧分为三栏 第一栏newsflash盒子&#xff0c;首先边框news-hd只写bottom&#xff0c;线条为dotted&#xff1b;然后news…

clickhouse -- clickhouse解析复杂JSON数组

举例 - 查数据 select _id,doctorId,patientId,diagnosisList from patient_disease final where diagnosisList is not null limit 3;- 解析数组 SELECT _id,doctorId,patientId,visitParamExtractRaw(diagnosisList,diagnosisName) FROM patient_disease final where _id …

甄知黄建华:从“天赋平平”到IT行业“六边形战士”,探索出企业数智化转型的“强IT”之路

本期我们先抛开人物和主体不表&#xff0c;从大环境开始谈起。随着科技的快速发展和全球商业环境的不断变化&#xff0c;中国企业对灵活性、创新性、全球化和效率的需求是迫切的&#xff0c;进行数字化转型来支撑企业的业务变革、组织优化已是业界共识。如何根据企业的实际情况…

【论文解读】NuScenes-QA:自动驾驶场景的多模态视觉问答基准

来源&#xff1a;投稿 作者&#xff1a;橡皮 编辑&#xff1a;学姐 论文链接&#xff1a;https://arxiv.org/pdf/2305.14836.pdf 开源代码&#xff1a;https://github.com/qiantianwen/NuScenes-QA 摘要&#xff1a; 我们在自动驾驶背景下引入了一种新颖的视觉问答&#xf…

2022年9月6日 Go生态洞察:Go的漏洞管理新支持

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…