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

26. Object.defineProperty 和 Proxy 用法

Object.definePropertyProxy 都是 JavaScript 中用于实现数据劫持和响应式系统的重要 API,它们在 Vue 等前端框架中被广泛使用。

Object.defineProperty

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

基本语法
Object.defineProperty(obj, prop, descriptor);
  • obj: 要定义属性的对象
  • prop: 要定义或修改的属性名称
  • descriptor: 要定义或修改的属性描述符
属性描述符
const obj = {};
Object.defineProperty(obj, "name", {value: "John", // 属性值writable: true, // 是否可写enumerable: true, // 是否可枚举configurable: true, // 是否可配置// 或者使用 getter 和 setterget() {return this._name;},set(value) {this._name = value;},
});
响应式实现示例
function reactive(obj) {const observed = {};Object.keys(obj).forEach((key) => {let value = obj[key];Object.defineProperty(observed, key, {get() {console.log(`获取 ${key}: ${value}`);return value;},set(newValue) {console.log(`设置 ${key}: ${newValue}`);value = newValue;},enumerable: true,configurable: true,});});return observed;
}const data = reactive({ name: "John", age: 25 });
console.log(data.name); // 获取 name: John
data.name = "Jane"; // 设置 name: Jane
Object.defineProperty 的局限性
  • 无法监听数组索引的变化
  • 无法监听对象属性的添加和删除
  • 必须遍历对象的每个属性进行劫持
  • 无法劫持嵌套对象

Proxy

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义。

基本语法
const proxy = new Proxy(target, handler);
  • target: 要代理的目标对象
  • handler: 包含拦截方法的对象
常用拦截操作
const target = {name: "John",age: 25,
};const proxy = new Proxy(target, {// 拦截属性读取get(target, prop, receiver) {console.log(`读取属性: ${prop}`);return Reflect.get(target, prop, receiver);},// 拦截属性设置set(target, prop, value, receiver) {console.log(`设置属性 ${prop}: ${value}`);return Reflect.set(target, prop, value, receiver);},// 拦截 in 操作符has(target, prop) {console.log(`检查属性存在: ${prop}`);return Reflect.has(target, prop);},// 拦截 delete 操作deleteProperty(target, prop) {console.log(`删除属性: ${prop}`);return Reflect.deleteProperty(target, prop);},
});console.log(proxy.name); // 读取属性: name
proxy.age = 30; // 设置属性 age: 30
"name" in proxy; // 检查属性存在: name
delete proxy.age; // 删除属性: age
响应式实现示例
function reactive(target) {if (typeof target !== "object" || target === null) {return target;}const handler = {get(target, key, receiver) {console.log(`获取属性: ${key}`);const result = Reflect.get(target, key, receiver);// 递归处理嵌套对象return typeof result === "object" ? reactive(result) : result;},set(target, key, value, receiver) {console.log(`设置属性 ${key}: ${value}`);const result = Reflect.set(target, key, value, receiver);return result;},};return new Proxy(target, handler);
}const data = reactive({name: "John",age: 25,hobbies: ["reading", "coding"],
});console.log(data.name); // 获取属性: name
data.hobbies.push("swimming"); // 获取属性: hobbies

两者对比

特性Object.definePropertyProxy
兼容性ES5,兼容性好ES6,需要现代浏览器支持
拦截能力有限,只能拦截特定属性强大,可拦截 13 种操作
数组监听无法直接监听数组索引可以完美监听数组变化
嵌套对象需要递归处理可以通过 get 递归处理
性能直接修改属性性能较好通过代理有一定性能损耗
使用复杂度需要遍历每个属性一次代理整个对象

在 Vue 中的应用

  • Vue 2: 使用 Object.defineProperty 实现响应式系统
  • Vue 3: 使用 Proxy 重构响应式系统,解决了 Vue 2 的诸多限制
// Vue 2 的限制示例
const vm = new Vue({data: {items: [1, 2, 3],},
});// 以下操作在 Vue 2 中无法被检测到
vm.items[0] = 2; // 通过索引设置数组项
vm.items.length = 0; // 修改数组长度
vm.newProperty = "value"; // 添加新属性// 需要使用 Vue 提供的 API
// Vue.set(vm.items, 0, 2) 或 vm.$set(vm.items, 0, 2)
// vm.items.splice(0)// Vue 3 中使用 Proxy 没有这些限制
http://www.dtcms.com/a/335774.html

相关文章:

  • 中级统计师-会计学基础知识-第五章 财务报告
  • 计算机算术6-SRT2除法
  • Linux817 shell:until,nfs,random
  • TypeScript中的import语法详解
  • 6.Ansible自动化之-管理变量和事实
  • 关于第一次接触Linux TCP/IP网络相关项目
  • 牛客周赛 Round 105
  • Java -- 坐标体系--绘图方法
  • 《详解 C++ Date 类的设计与实现:从运算符重载到功能测试》
  • Originality AI:原创度和AI内容检测工具
  • thingsboard 服务器在2核CPU、2G内存资源配置下如何调优提速,适合开发/演示
  • 飞算JavaAI赋能高吞吐服务器模拟:从0到百万级QPS的“流量洪峰”征服之旅
  • C#读取文件, IO 类属性及使用示例
  • [GLM-4.5] GLM-4.5模型 | Claude Code服务集成
  • Qt 5.5 的安装与配置(使用 VSCode编辑)
  • React 基础实战:从组件到案例全解析
  • Talk2BEV论文速读
  • 什么叫作数据处理?数据处理和数据治理是什么关系
  • Java StringBuffer使用详解
  • Spring MVC 九大组件源码深度剖析(四):HandlerMapping - 请求映射的玄机
  • 电力设备状态监测与健康管理:基于多源异构数据融合的技术实现
  • 【龙泽科技】汽车车身测量与结构件更换仿真教学软件【GEELY+CHIEF】
  • Wasserstein GAN:如何解决GANS训练崩溃,深入浅出数学原理级讲解WGAN与WGAN-GP
  • (机器学习)监督学习 vs 非监督学习
  • 机器学习05-朴素贝叶斯算法
  • Elasticsearch 在向量捜索中使用 Direct I0
  • java-maven
  • 佳文赏读 || (CVPR 2025新突破) Robobrain:机器人操作从抽象到具体的统一大脑模型(A Unified Brain Model)
  • 【教程】笔记本安装FnOS设置合盖息屏不休眠
  • Pulsar存储计算分离架构设计之存储层BookKeeper(上)