当前位置: 首页 > news >正文

Object.defineProperty() 完整指南

Object.defineProperty() 完整指南

1. 基本概念

Object.defineProperty() 方法允许精确地添加或修改对象的属性。默认情况下,使用此方法添加的属性是不可修改的。

1.1 基本语法

Object.defineProperty(obj, prop, descriptor)

参数说明:

  • obj: 要定义属性的对象
  • prop: 要定义或修改的属性名
  • descriptor: 属性描述符对象

2. 属性描述符

2.1 数据描述符

const obj = {};Object.defineProperty(obj, 'name', {value: 'John',          // 属性值writable: true,         // 是否可写enumerable: true,       // 是否可枚举configurable: true      // 是否可配置
});

2.2 访问器描述符

const obj = {_name: 'John'
};Object.defineProperty(obj, 'name', {get() {return this._name;},set(value) {this._name = value;},enumerable: true,configurable: true
});

3. 实际应用示例

3.1 数据劫持(Vue2响应式原理)

function observe(obj) {if (typeof obj !== 'object' || obj === null) {return;}Object.keys(obj).forEach(key => {defineReactive(obj, key, obj[key]);});
}function defineReactive(obj, key, val) {// 递归处理嵌套对象observe(val);Object.defineProperty(obj, key, {get() {console.log(`获取${key}属性`);return val;},set(newVal) {if (val === newVal) return;console.log(`设置${key}属性为${newVal}`);val = newVal;// 触发更新}});
}// 使用示例
const data = {name: 'John',age: 20
};observe(data);
data.name = 'Mike'; // 设置name属性为Mike
console.log(data.name); // 获取name属性 Mike

3.2 私有属性模拟

function Person(name) {let _name = name;Object.defineProperty(this, 'name', {get() {return _name;},set(value) {if (typeof value !== 'string') {throw new Error('Name must be a string');}_name = value;}});
}const person = new Person('John');
console.log(person.name); // John
person.name = 'Mike'; // 正常设置
person.name = 123; // 抛出错误

3.3 计算属性实现

function computed(obj, key, computeFunc) {let value = computeFunc();Object.defineProperty(obj, key, {get() {return value;},set() {console.warn(`${key} is a computed property, cannot be modified`);}});
}const obj = {a: 1,b: 2
};computed(obj, 'sum', () => obj.a + obj.b);
console.log(obj.sum); // 3
obj.sum = 10; // 警告:sum is a computed property, cannot be modified

4. 注意事项和限制

4.1 不可扩展对象

const obj = {};
Object.preventExtensions(obj);// 这将抛出错误
Object.defineProperty(obj, 'name', {value: 'John'
});

4.2 继承属性

const parent = {};
Object.defineProperty(parent, 'name', {value: 'John',writable: false
});const child = Object.create(parent);
// 这将抛出错误
child.name = 'Mike';

4.3 属性描述符限制

const obj = {};// 不能同时指定 value/writable 和 get/set
Object.defineProperty(obj, 'name', {value: 'John',get() {return 'John';}
}); // 抛出错误

5. 性能考虑

5.1 大量属性处理

// 不推荐
const obj = {};
for (let i = 0; i < 1000; i++) {Object.defineProperty(obj, `prop${i}`, {value: i,writable: true});
}// 推荐
const descriptors = {};
for (let i = 0; i < 1000; i++) {descriptors[`prop${i}`] = {value: i,writable: true,configurable: true,enumerable: true};
}
Object.defineProperties(obj, descriptors);

5.2 访问器性能

// 避免在访问器中进行复杂计算
Object.defineProperty(obj, 'name', {get() {// 不推荐return complexCalculation();}
});// 推荐:缓存计算结果
let cachedValue;
Object.defineProperty(obj, 'name', {get() {if (cachedValue === undefined) {cachedValue = complexCalculation();}return cachedValue;}
});

6. 最佳实践

  1. 描述符默认值
// 记住默认值都是 false
Object.defineProperty(obj, 'name', {value: 'John'// writable: false// enumerable: false// configurable: false
});
  1. 使用 TypeScript 类型
interface PropertyDescriptor {configurable?: boolean;enumerable?: boolean;value?: any;writable?: boolean;get?(): any;set?(v: any): void;
}
  1. 错误处理
function safeDefineProperty(obj, prop, descriptor) {try {Object.defineProperty(obj, prop, descriptor);return true;} catch (error) {console.error(`Failed to define property ${prop}:`, error);return false;}
}

7. 总结

Object.defineProperty() 的关键点:

  1. 使用场景

    • 数据劫持
    • 私有属性模拟
    • 计算属性实现
    • 属性访问控制
  2. 注意事项

    • 描述符类型限制
    • 性能考虑
    • 继承关系处理
    • 错误处理
  3. 最佳实践

    • 合理使用缓存
    • 避免复杂计算
    • 注意默认值
    • 做好错误处理

10. 深入理解 Object.defineProperty()

10.1 基础概念详解

Object.defineProperty() 是 JavaScript 中用于在对象上定义新属性或修改现有属性的方法。它允许精确控制属性的特性。

// 基本语法
Object.defineProperty(obj, prop, descriptor)// 参数说明
// obj: 要定义属性的对象
// prop: 要定义或修改的属性名
// descriptor: 属性描述符对象

10.2 属性描述符详解

属性描述符分为两种类型:数据描述符和访问器描述符。

  1. 数据描述符的完整选项:
const obj = {};
Object.defineProperty(obj, 'name', {value: 'John',          // 属性值writable: true,         // 是否可写enumerable: true,       // 是否可枚举configurable: true      // 是否可配置
});
  1. 访问器描述符的完整选项:
const obj = {_name: 'John'
};
Object.defineProperty(obj, 'name', {get() {console.log('Getting value');return this._name;},set(value) {console.log('Setting value to', value);this._name = value;},enumerable: true,configurable: true
});

10.3 常见使用场景

  1. 只读属性:
const obj = {};
Object.defineProperty(obj, 'readonly', {value: 'I am read-only',writable: false,enumerable: true,configurable: false
});obj.readonly = 'New value'; // 无效
console.log(obj.readonly);  // 'I am read-only'
  1. 不可枚举属性:
const obj = {};
Object.defineProperty(obj, 'hidden', {value: 'You cannot see me',enumerable: false
});console.log(Object.keys(obj)); // []
console.log(obj.hidden);       // 'You cannot see me'
  1. 计算属性:
const person = {firstName: 'John',lastName: 'Doe'
};Object.defineProperty(person, 'fullName', {get() {return `${this.firstName} ${this.lastName}`;},set(value) {[this.firstName, this.lastName] = value.split(' ');}
});console.log(person.fullName);    // 'John Doe'
person.fullName = 'Jane Smith';
console.log(person.firstName);   // 'Jane'
console.log(person.lastName);    // 'Smith'
  1. Vue 双向绑定实现:
function observe(obj) {if (!obj || typeof obj !== 'object') return;// 遍历对象的每个属性Object.keys(obj).forEach(key => {let value = obj[key];let dep = new Dep(); // 依赖收集器Object.defineProperty(obj, key, {get() {// 收集依赖if (Dep.target) {dep.addDep(Dep.target);}return value;},set(newValue) {if (value === newValue) return;value = newValue;// 通知所有依赖进行更新dep.notify();}});// 递归观察子属性if (typeof value === 'object') {observe(value);}});
}// 使用示例
const data = {user: {name: 'John',age: 20}
};observe(data);
// 现在 data 对象的所有属性都是响应式的

10.4 注意事项和最佳实践

  1. 描述符限制:
// 不能同时使用数据描述符和访问器描述符
Object.defineProperty(obj, 'prop', {value: 123,get() { return 123; } // 错误!
});
  1. 性能优化:
// 批量定义属性
Object.defineProperties(obj, {prop1: {value: 123,writable: true},prop2: {get() { return this.prop1 * 2; }}
});
  1. 默认值处理:
// 所有描述符属性默认为 false
Object.defineProperty(obj, 'prop', {value: 123// writable: false// enumerable: false// configurable: false
});

相关文章:

Object.defineProperty() 完整指南

Object.defineProperty() 完整指南 1. 基本概念 Object.defineProperty() 方法允许精确地添加或修改对象的属性。默认情况下&#xff0c;使用此方法添加的属性是不可修改的。 1.1 基本语法 Object.defineProperty(obj, prop, descriptor)参数说明&#xff1a; obj: 要定义…...

postgresql函数创建

postgresql的函数创建 1.创建函数的基本语法&#xff1a; CREATE [OR REPLACE] FUNCTION function_name(parameter_list) RETURNS return_type AS $$ BEGIN -- 函数体 END; $$ LANGUAGE language_name;2.创建函数时传入参数示例:add_user tbl_user表 | id | username | …...

ECMAScript 变量

文章目录 前言一、ECMAScript 变量二、var 关键字1、var 声明作用域2、var 声明提升(hoist)三、let 关键字四、const 关键字🔰 总结前言 任何语言的核心所描述的都是这门语言在最基本的层面上如何工作,涉及 语法、操作符、数据类型以及内置功能,在此基础之上才可以构建复…...

CAN总线波形中最后一位电平偏高或ACK电平偏高问题分析

参考&#xff1a;https://zhuanlan.zhihu.com/p/689336144 有时候看到CAN总线H和L的差值波形的最后一位电平会变高很多&#xff0c;这是什么原因呢&#xff1f; 实际上这是正常的现象&#xff0c;最后一位是ACK位。问题描述为&#xff1a;CAN总线ACK电平偏高。 下面分析下原因…...

【C++】22___STL常用算法

目录 一、常用遍历算法 二、常用查找算法 2.1 find 2.2 其它查找算法 三、常用排序算法 3.1 sort 3.2 其它排序算法 四、拷贝 & 替换 4.1 copy 4.2 其它算法 五、常用的算数生成算法 5.1 accumulate 5.2 fill 六、常用集合算法 6.1 set_intersection 6…...

意静明和-十成

十成 责任&#xff08;健康&#xff09;、使命&#xff08;事业&#xff09;、信念&#xff08;意义&#xff09;、自律&#xff08;排诱&#xff09;、自修&#xff08;知识&#xff09;、总结&#xff08;四为&#xff09;、执行&#xff08;一事不拖&#xff09;、人情&…...

easyui textbox使用placeholder无效

easyui textbox使用placeholder无效 在easyui 的textbox控件&#xff0c;请使用data-options 设定 示例 <input type text class easyui-textbox data-options "prompt:请输入您的邮箱"/>...

flux中的缓存

1. cache&#xff0c;onBackpressureBuffer。都是缓存。cache可以将hot流的数据缓存起来。onBackpressureBuffer也是缓存&#xff0c;但是当下游消费者的处理速度比上游生产者慢时&#xff0c;上游生产的数据会被暂时存储在缓冲区中&#xff0c;防止丢失。 2. Flux.range 默认…...

代码重定位详解

文章目录 一、段的概念以及重定位的引入1.1 问题的引入1.2 段的概念1.3 重定位 二、如何实现重定位2.1 程序中含有什么&#xff1f;2.2 谁来做重定位&#xff1f;2.3 怎么做重定位和清除BSS段&#xff1f;2.4 加载地址和链接地址的区别 三、散列文件使用与分析3.1 重定位的实质…...

活动预告 | Microsoft 365 在线技术公开课:让组织针对 Microsoft Copilot 做好准备

课程介绍 通过Microsoft Learn免费参加Microsoft 365在线技术公开课&#xff0c;建立您需要的技能&#xff0c;以创造新的机会并加速您对Microsoft云技术的理解。参加我们举办的“让组织针对 Microsoft Copilot for Microsoft 365 做好准备” 在线技术公开课活动&#xff0c;学…...

从0到机器视觉工程师(一):机器视觉工业相机总结

目录 相机的作用 工业相机 工业相机的优点 工业相机的种类 工业相机知名品牌 光源与打光 打光方式 亮暗场照明 亮暗场照明的应用 亮暗场照明的区别 前向光漫射照明 背光照明 背光照明的原理 背光照明的应用 同轴光照明 同轴光照明的应用 总结 相机的作用 相机…...

Docker安装(Docker Engine安装)

一、Docker Engine和Desktop区别 Docker Engine 核心组件&#xff1a;Docker Engine是Docker的核心运行时引擎&#xff0c;负责构建、运行和管理容器。它包括守护进程&#xff08;dockerd&#xff09;、API和命令行工具客户端&#xff08;docker&#xff09;。适用环境&#…...

数组的深度监听deep

场景&#xff1a;组件提供的emit事件可能被占用&#xff0c;在不能使用事件提交的情况下&#xff0c;就要上watch数组监听了&#xff0c;但是是发现只有在数组的长度发生变化的时候才会触发监听&#xff0c;这怎么行。。。。。 对于对象数组的深度监听&#xff0c;如果没有正确…...

点击锁定按钮,锁定按钮要变成解锁按钮,然后状态要从待绑定变成 已锁定(升级版)

文章目录 1、updateInviteCodeStatus2、handleLock3、InviteCodeController4、InviteCodeService5、CrudRepository 点击锁定按钮&#xff0c;锁定按钮要变成解锁按钮&#xff0c;然后状态要从待绑定变成 已锁定&#xff1a;https://blog.csdn.net/m0_65152767/article/details…...

UniApp 性能优化策略

一、引言 在当今数字化时代&#xff0c;移动应用的性能成为影响用户留存与满意度的关键因素。UniApp 作为一款热门的跨平台开发框架&#xff0c;以一套代码适配多端的特性极大提升了开发效率&#xff0c;但同时也面临着性能优化的挑战。优化 UniApp 性能&#xff0c;不仅能够让…...

【Linux报告】实训六 重置超级用户密码

实训六 重置超级用户密码 2018编写-今日公布 【练习一】忘记root密码 步骤一&#xff1a;开启或重启系统&#xff0c;并且要在五秒之内按任何键&#xff1b; 步骤二&#xff1a;按任意键&#xff0c;停止进入系统&#xff0c;按【e】键&#xff0c;跳转新页面&#xff0c;再…...

smolagents:一个用于构建代理的简单库

HF推出 smolagents&#xff0c;一个非常简单的库&#xff0c;它能够解锁语言模型的代理功能。以下是它的简要介绍&#xff1a; from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModelagent CodeAgent(tools[DuckDuckGoSearchTool()], modelHfApiModel())agent…...

通过Dockerfile来实现项目可以指定读取不同环境的yml包

通过Dockerfile来实现项目可以指定读取不同环境的yml包 1. 挂载目录2. DockerFile3. 运行脚本deploy.sh4. 运行查看日志进入容器 5. 接口测试修改application-dev.yml 6. 优化Dockerfile7. 部分参数解释8. 优化不同环境下的日志也不同调整 Dockerfile修改部署脚本 deploy.sh重新…...

云手机 —— 手机矩阵的 “超级外挂

如何打造手机矩阵 打造手机矩阵主要包括以下几个步骤: 1.确定目标与需求:首先&#xff0c;明确打造手机矩阵的目的和需求&#xff0c;是为了进行电商运营、自媒体推广、任务管理还是其他目的。这将决定后续的手机数量、操作系统选择以及应用安装等。 2.选择手机与操作系统:根据…...

OpenCV的TickMeter计时类

OpenCV的TickMeter计时类 1. TickMeter是一个计时的类1.1 计算耗时1.2 计算循环的平均耗时和FPS1.3 function 2. 案例 1. TickMeter是一个计时的类 https://docs.opencv.org/4.x/d9/d6f/classcv_1_1TickMeter.html#details 1.1 计算耗时 TickMeter tm;tm.start();// do some…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...