理解defineProperty以及getter、setter

文章目录

    • 对象属性注意点
    • 理解`defineProperty`
    • 描述符的原型与默认值
    • getter和setter

理解defineProperty以及getter、setter,学习它们之间的联系

对象属性注意点

我们一般修改对象通过obj.key这样的方式访问到,要设置/修改对象的属性,只需要obj.key="value"
如果key位于原型上,同时在对象自身设置该key值时,修改的是对象自身这个值,而不是修改原型上的

let arr = [1, 2, 3];
arr.__proto__.test = "我是原型上的"; // 这种写法不推荐,这样写不具有可维护性和可读性
arr.test = "我是自身上的";
console.log(arr); // [ 1, 2, 3, test: '我是自身上的' ]
console.log(arr.__proto__); // Object(0) [ test: '我是原型上的' ]

原型上的属性有时候会被for in给遍历出来:

let arr = [1, 2, 3];
arr.__proto__.test = "我是原型";
for (let i in arr) {console.log(arr[i]);
}
// 1
// 2
// 3
// 我是原型

所以用for in,一般都是搭配hasOwnProperty判断当前对象属性中是否具有指定的属性(也就是指定的键),或者直接使用forEach

理解defineProperty

上面__proto__直接修改原型的写法不推荐,不具备可维护性和可读性,__proto__是一个内部属性,并不是ECMAScript属性。
Object.defineProperty()是定义新属性或修改原有属性并且能够设置其特性的标准方法,它可以提供该属性的更多特性,比如可以设置属性是否可写、可枚举和可配置。该方法返回修改后的对象。

// 完整语法
Object.defineProperty(obj, prop, descriptor);
// obj 目标对象
// prop 属性名称
// descriptor 属性描述符
let obj = {};
Object.defineProperty(obj, "age", {value: "我不一样", // 属性对应的值writable: true, // 是否可写enumerable: true, // 可枚举configurable: true, // 可配置
});

descriptor这个参数可以分为两类:数据描述符(data descriptor)、访问描述符(accessor descriptor)。

  • 必选项
    1. configurable:表示可配置,当它为true时,该属性的描述符可被修改,并且该属性可被delete删除;同理,为false时,无法再调用defineProperty去修改描述符,也不可通过delete删除
    2. enumerable:表示可枚举,为true时,该属性可被迭代器枚举出来。比如使用for in或者Object.keys
  • 数据描述符
    1. value:该属性的值,通过obj.key访问时返回。
    2. writable:表示该属性是否可写,为false时,属性不可被任何赋值语句重写,但是此时还可以调用defineProperty来修改value,前提是configurable为true。

描述符的原型与默认值

一般先创建一个descriptor对象,然后传给defineProperty方法:

let descriptor = {writable: false,
};
Object.defineProperty(obj, "key", descriptor);

上面情况存在一定的风险,如果descriptor的原型上有相关特性,也会通过原型链被访问到,算入在对key的定义中:

descriptor.__proto__.enumerable = true;
Object.defineProperty(obj, "key", descriptor);
Object.getOwnPropertyDescriptor(obj, "key"); //  { value: undefined, enumerable: true, }

为了避免上面的意外情况,官方建议使用Object.freeze冻结对象,或者使用Object.create(null)创建一个新纯净的对象(不含原型)来使用。

let obj = {name: "我不是普通人",age: 123,
};
obj.__proto__.habit = "晕";
// Object.freeze() 返回值是被冻结的对象,该对象完全等于传入的对象,一般是不需要接收返回值
Object.freeze(obj);
// 不能添加新属性
// 不能删除已有属性
// 不能修改已有属性的值
// 不能修改已有属性的值
// 不能修改原型
// 不能修改已有属性的可枚举性、可配置性、可写性// 如果不知道一个对象是否被冻结 可以使用 Object.isFrozen() 来判断
console.log(Object.isFrozen(obj)); // true

VueObject.freeze在data中可以这样写:

// 对于纯展示的大数据,可以提升性能
data() {return {list: Object.freeze({name: "我不需要改变",})};  
},

一个对象属性描述符的默认值,一般都为true:

let obj = {};
obj.value = "看看默认值";
Object.getOwnPropertyDescriptor(obj, "value");
// { value: 123, writable: true, enumerable: true, configurable: true }

如果使用defineProperty定义的属性,默认值就不是这样的:

let obj = {};
Object.defineProperty(obj, "key", {value: 123,
});
console.log(Object.getOwnPropertyDescriptor(obj, "key"));
// { value: 456, writable: false, enumerable: false, configurable: false }

getter和setter

这两个就是上面提到的访问描述符,这只是两个概念,并没有这样的属性。

  • get

    是一个函数,访问该属性时会自动调用,函数的返回值为该属性的value。默认值为undefined。

  • set

    是一个函数,该属性赋值时会自动调用,新值会被当做参数传入。

Vue2框架中数据监控用到的核心原理就是这个。

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

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

相关文章

贴吧软件怎么切换ip

在网络使用中,有时我们需要切换IP地址来满足特定的需求,比如需要切换贴吧软件IP以进行不同的操作。本文将介绍几种贴吧切换IP地址的方法,帮助用户更好地管理自己的网络身份和访问权限。 1、更换网络环境‌ 通过连接到不同的Wi-Fi网络或使用移…

解决雪花ID在前端精度丢失问题

解决雪花ID在前端精度丢失问题 在现代分布式系统中,雪花算法(Snowflake)被广泛用于生成唯一的ID。这些ID通常是Long类型的整数。然而,当这些ID从后端传递到前端时,JavaScript的精度限制可能会导致精度丢失&#xff0c…

Android 电源管理各个版本的变动和限制

由于Android设备的电池容量有限,而用户在使用过程中会进行各种高耗电操作,如网络连接、屏幕亮度调节、后台程序运行等,因此需要通过各种省电措施来优化电池使用‌,延长电池续航时间,提高用户体验,并减少因电…

容器管理工具Docker

├──5-容器管理工具Docker | ├──1-容器管理工具Docker | | ├──1-应用部署容器化演进之路 | | ├──10-Docker容器数据持久化存储机制 | | ├──11-Docker容器服务编排利器DockerCompose应用实战 | | ├──12-Docker主机集群化方案DockerSwarm | …

docker compose入门1—概念介绍

Docker Compose 是 Docker 的一个工具,专门用于定义和运行多容器 Docker 应用程序。它通过使用一个配置文件(通常是 docker-compose.yml)来简化管理多个容器的流程,尤其适用于开发、测试和轻量级的生产环境。Compose 工具可以帮助…

开源的云平台有哪些?

开源云平台为用户提供了构建、管理和运行云基础设施及应用的能力,同时允许社区参与开发和改进。以下是一些知名的开源云平台: 1. OpenStack 简介:OpenStack:一个广泛使用的开源云平台,它由多个组件组成,提…

【ubuntu】修改用户名、主机名、主文件夹名、登录名、密码

目录 1.他们是什么 2.修改方法 2.1 修改用户密码 2.2 修改主机名 2.2.1 切换到root用户 2.2.2 修改名称 2.3 修改用户名 主文件夹名 登录名 2.2.1 sudoers 2.2.2 passwd 2.2.3 shadow 2.2.4 group 2.2.5 修改主文件夹名 3.重启 1.他们是什么 (1&#xf…

一键生成PPT的AI工具-Kimi!

一键生成PPT的AI工具-Kimi! 前言介绍Kimi为什么选择Kimi如何使用Kimi在线编辑PPT下载生成的PPT自己编辑 结语 😀大家好!我是向阳🌞,一个想成为优秀全栈开发工程师的有志青年! 📔今天不来讨论前后…

Rust语言特性简介

Rust语言在操作系统开发中的创新之处主要体现在以下几个方面: 内存安全:Rust的所有权模型和借用检查器在编译时保证了内存安全,减少了空指针解引用、缓冲区溢出等错误,这对于操作系统内核开发来说至关重要。 并发性:R…

前端反接保护:实用方案解析与探讨

前端反接保护通常采用肖特基二极管方案或PMOS/NMOS方案,本文另外介绍一种理想二极管方案。 1、肖特基二极管方案 由于肖特基二极管具有正向导通电压,只能用于小电流场合,甚至于直接使用普通的整流二极管。比如1A电流,设D1的正向…

STM32的USART技术介绍

USART(Universal Synchronous/Asynchronous Receiver/Transmitter,通用同步/异步收发传输器)是STM32微控制器中常用的串行通信接口之一。它支持同步和异步通信模式,广泛应用于各种数据传输场景,如串口通信、GPS模块连接…

OJ在线评测系统 微服务 用分布式消息队列 RabbitMQ 解耦判题服务和题目服务 手搓交换机和队列 实现项目异步化

消息队列解耦 项目异步化 分布式消息队列 分布式消息队列是一种用于异步通信的系统,它允许不同的应用程序或服务之间传递消息。消息队列的核心理念是将消息存储在一个队列中,发送方可以将消息发送到队列,而接收方则可以在适当的时候从队列中…

系统架构设计师论文《论企业集成平台的理解与应用》精选试读

论文真题 企业集成平台(Enterprise Imtcgation Plaform,EIP)是支特企业信息集成的像环境,其主要功能是为企业中的数据、系统和应用等多种对象的协同行提供各种公共服务及运行时的支撑环境。企业集成平台能够根据业务模型的变化快速地进行信息系统的配置…

面试(十)

目录 一. 单元测试 二. FreeRTOS和裸机哪个实时性好? 三. 怎么判断某个程序的运行时间 四. 函数指针 五. 全局变量被线程使用冲突 5.1 使用互斥锁 5.2 使用读写锁 5.3 使用原子操作 六. 局部变量没有初始化是什么值 七. uint_8 n 255 , n等于多少 八. …

如何优化低计算密集度神经网络在GPU和NPU上的性能

在深度学习领域,GPU 和 NPU 是常用的硬件加速器,它们凭借强大的并行计算能力显著提升了深度神经网络(DNN)的训练和推理速度。然而,并不是所有模型在 GPU 和 NPU 上都能得到理想的性能提升。对于一些计算密集度较低的任…

单体到微服务架构服务演化过程

单体到微服务架构服务演化过程 架构服务化 聊聊从单体到微服务架构服务演化过程 单体分层架构 在 Web 应用程序发展的早期,大部分工程是将所有的服务端功能模块打包到单个巨石型(Monolith)应用中,譬如很多企业的 Java 应用程序…

3、Docker搭建MQTT及Spring Boot 3.x集成MQTT

一、前言 本篇主要是围绕着两个点,1、Docker 搭建单机版本 MQTT(EMQX),2、Spring Boot 3.x 集成 MQTT(EMQX); 而且这里的 MQTT(EMQX)的搭建也只是一个简单的过程&#x…

数据结构单向链表

单向链表的转置 转置的思想: (1) 将头节点与当前链表断开,断开前保存下头节点的下一个节点,保证后面链表能找得到,定义一个q保存头节点的下一个节点,断开后前面相当于一个空的链表,后面是一个无头的单向链表…

uni-app之旅-day03-搜索

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 5. 搜索5.0 创建 search 分支5.1 自定义搜索组件5.1.2 my-search.vue组件通过自定义属性增强组件的通用性5.1.3 为自定义组件封装 click 事件 5.2 搜索建议5.2.1 渲…

C++拾趣——绘制Console中DropdownMenu

大纲 居中显示窗口清屏并重设光标绘制窗口绘制窗口顶部绘制下拉行绘制下拉框选项绘制按钮行绘制窗口底部 修改终端默认行为对方向键的特殊处理过程控制Tab键的处理Enter键的处理上下左右方向键的处理 完整代码代码地址 这次我们要绘制下拉菜单,如下图。 居中显示窗口…