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

JavaScript中Object.defineProperty的作用和用法以及和proxy的区别

在 JavaScript 中,Object.defineProperty() 是一个强大的内置方法,用于精确控制对象属性的配置。它允许你直接修改对象属性的底层特性(如可读写性、可枚举性、可配置性),甚至可以自定义属性的 getter 和 setter 方法。

核心作用

  1. 精确控制属性配置
    通过设置属性描述符(descriptor),可以精确控制属性的行为。
  2. 实现数据劫持
    通过 getter/setter 拦截属性的读取和赋值操作,常用于响应式系统(如 Vue.js 的数据绑定)。
  3. 阻止属性被意外修改
    通过设置 writable: falseconfigurable: false 保护属性不被修改或删除。

基本语法

Object.defineProperty(obj, prop, descriptor);
  • obj:需要定义属性的对象。
  • prop:需要定义或修改的属性名称(字符串或 Symbol)。
  • descriptor:属性描述符对象,包含以下可选键:
    • value:属性的值(默认 undefined)。
    • writable:属性值是否可修改(默认 false)。
    • enumerable:属性是否可被枚举(如 for...in 循环,默认 false)。
    • configurable:属性是否可被删除或重新配置(默认 false)。
    • get:获取属性值的函数(与 value 互斥)。
    • set:设置属性值的函数(与 value 互斥)。

用法示例

1. 基本属性定义
const person = {};Object.defineProperty(person, 'name', {value: 'John',writable: true,     // 允许修改值enumerable: true,   // 可被枚举configurable: true  // 可被重新配置或删除
});console.log(person.name); // "John"
person.name = 'Jane';     // 修改有效(writable: true)
console.log(person.name); // "Jane"
2. 只读属性(writable: false
const person = {};Object.defineProperty(person, 'age', {value: 30,writable: false,    // 只读enumerable: true
});console.log(person.age); // 30
person.age = 31;         // 赋值无效(严格模式下会报错)
console.log(person.age); // 30
3. 不可枚举属性(enumerable: false
const person = { name: 'John' };Object.defineProperty(person, 'age', {value: 30,enumerable: false   // 不可枚举
});console.log(person.age); // 30
for (const key in person) {console.log(key); // 仅输出 "name"(age 不可枚举)
}
4. 不可配置属性(configurable: false
const person = {};Object.defineProperty(person, 'name', {value: 'John',configurable: false  // 不可重新配置或删除
});delete person.name;    // 删除无效
console.log(person.name); // "John"// 尝试重新配置会报错(严格模式下)
Object.defineProperty(person, 'name', {value: 'Jane'
}); // TypeError: Cannot redefine property: name
5. 数据劫持(getter/setter)
const person = {_age: 30 // 约定使用下划线表示私有属性
};Object.defineProperty(person, 'age', {get() {console.log('读取 age');return this._age;},set(newValue) {console.log('设置 age 为', newValue);if (newValue < 0) throw new Error('年龄不能为负数');this._age = newValue;}
});console.log(person.age); // 读取 age → 30
person.age = 31;         // 设置 age 为 31
person.age = -5;         // Error: 年龄不能为负数

应用场景

  1. 实现响应式系统
    Vue.js 2.x 利用 Object.defineProperty() 实现数据劫持,当属性值变化时自动更新 DOM:

    function defineReactive(obj, key, value) {Object.defineProperty(obj, key, {get() {// 依赖收集return value;},set(newValue) {if (value !== newValue) {value = newValue;// 触发更新updateDOM();}}});
    }
    
  2. 实现私有属性
    通过 getter/setter 控制属性访问权限:

    const person = {};
    let _age = 30; // 闭包中的私有变量Object.defineProperty(person, 'age', {get() { return _age; },set(value) { _age = value; }
    });
    
  3. 阻止对象被篡改
    通过设置 configurable: falsewritable: false 保护关键属性:

    const config = { API_KEY: 'secret' };Object.defineProperty(config, 'API_KEY', {writable: false,configurable: false
    });// 无法修改或删除 API_KEY
    

注意事项

  1. 兼容性Object.defineProperty() 是 ES5 引入的方法,不支持 IE8 及以下版本。
  2. 性能影响:频繁触发 getter/setter 会有一定性能开销,避免在高性能场景(如大型循环)中过度使用。
  3. 深度监听Object.defineProperty() 只能监听对象的直接属性,若要监听嵌套对象,需要递归处理。
  4. 数组监听限制:直接监听数组变化存在局限性(Vue.js 3 改用 Proxy 解决此问题)。

Proxy 的对比

特性Object.defineProperty()Proxy
监听范围只能监听对象的已有属性(需逐个定义)可以监听整个对象(包括新增属性)
数组支持对数组的监听有限(需特殊处理)全面支持数组操作
元编程能力仅能控制单个属性可以拦截多种操作(如 indelete
兼容性ES5(支持 IE9+)ES6(不支持 IE)

Object.defineProperty() 是 JavaScript 中强大的元编程工具,适合需要精确控制对象属性行为的场景,尤其在实现响应式系统、数据验证和属性保护等方面有广泛应用。

http://www.dtcms.com/a/279115.html

相关文章:

  • 优化菜品呈现:让菜品自己 “开口” 求传播
  • 【ASP.NET Core】内存缓存(MemoryCache)原理、应用及常见问题解析
  • 我的Qt八股文笔记2:Qt并发编程方案对比与QPointer,智能指针方案
  • 电气安全监测系统:筑牢电气安全防线
  • DAOS系统架构-Container
  • 壹[1],异步与多线程
  • 美联储降息趋缓叠加能源需求下调,泰国证券交易所新一代交易系统架构方案——高合规、强韧性、本地化的跨境金融基础设施解决方案
  • 【Linux】Ubuntu22.04安装zabbix
  • 固态金属储氢实用化提速:新氢动力 20 公斤级系统重磅发布
  • GaussDB in的用法
  • Linux部署Mysql
  • JavaScript进阶篇——第一章 作用域与垃圾回收机制
  • Netty编程模型介绍
  • 每天学习一个Python库之os库
  • Debezium日常分享系列之:Debezium 3.2.0.Final发布
  • MySQL Innodb Cluster配置
  • Ubuntu服务器安装Miniconda
  • VS2019编译使用log4cplus 1.2.0
  • AI数字人正成为医药行业“全场景智能角色”,魔珐科技出席第24届全国医药工业信息年会
  • DataWhale AI夏令营 Task2笔记
  • Linux —— A / 基础指令
  • 【牛客LeetCode数据结构】单链表的应用——合并两个有序链表问题、链表的回文结构问题详解
  • 游戏设备软件加密锁复制:技术壁垒与安全博弈
  • js与vue基础学习
  • 鸿蒙应用开发: 鸿蒙项目中使用私有 npm 插件的完整流程
  • docker-compose 安装Alist
  • Cesium源码打包
  • 数字孪生技术驱动UI前端革新:实现产品设计的虚拟仿真与实时反馈
  • Django Admin 配置详解
  • 【更新至2024年】2009-2024年上市公司华证esg评级、评分数据(含细分项)(年度+季度)