Object.defineProperty 与 Proxy解析

以下是关于 Object.definePropertyProxy 的核心知识点解析、对比及使用场景说明:


1. Object.defineProperty

核心功能
  • 定义或修改对象属性的特性:如 valuewritableenumerableconfigurable
  • 数据劫持:通过 gettersetter 监听属性的读取和修改。
基本语法
Object.defineProperty(obj, prop, {
  value: 1,          // 属性值
  writable: true,    // 是否可修改
  enumerable: true,  // 是否可枚举(如出现在 for-in 循环中)
  configurable: true,// 是否可删除或重新配置
  // 存取描述符(与 value/writable 互斥)
  get() { return this._value; },
  set(newVal) { this._value = newVal; }
});
示例:实现简单数据响应式
const data = { count: 0 };

Object.defineProperty(data, 'count', {
  get() {
    console.log('读取 count');
    return this._count;
  },
  set(newVal) {
    console.log('更新 count');
    this._count = newVal;
  }
});

data.count = 10; // 输出: "更新 count"
console.log(data.count); // 输出: "读取 count" → 10
缺点
  • 无法监听新增/删除属性:需手动调用 Vue.setVue.delete(Vue 2 的限制)。
  • 数组监听需特殊处理:通过重写数组方法(如 pushpop)。
  • 性能问题:需递归遍历对象所有属性。

2. Proxy

核心功能
  • 代理整个对象:拦截对象的 13 种操作(如属性读取、赋值、删除、函数调用等)。
  • 更强大的监听能力:支持监听新增属性、数组变化等。
基本语法
const proxy = new Proxy(target, {
  get(target, prop, receiver) { /* 拦截读取 */ },
  set(target, prop, value, receiver) { /* 拦截赋值 */ },
  deleteProperty(target, prop) { /* 拦截删除 */ },
  // 其他拦截器:has、apply、construct 等
});
示例:实现数据响应式
const data = { count: 0 };

const proxy = new Proxy(data, {
  get(target, prop) {
    console.log(`读取 ${prop}`);
    return Reflect.get(target, prop);
  },
  set(target, prop, value) {
    console.log(`更新 ${prop}${value}`);
    return Reflect.set(target, prop, value);
  }
});

proxy.count = 10; // 输出: "更新 count 为 10"
console.log(proxy.count); // 输出: "读取 count" → 10
优势
  • 全面监听:支持属性新增、删除、数组方法(如 push)等。
  • 性能优化:无需初始化遍历对象属性。
  • 非侵入性:直接代理对象,不修改原对象。

3. 核心对比

特性Object.definePropertyProxy
监听范围只能监听已存在的属性监听整个对象的所有操作
数组支持需重写数组方法直接监听数组变化(如 push
性能初始化时递归遍历属性,性能较低按需拦截,性能更高
兼容性支持 IE9+支持现代浏览器(IE 不支持)
使用复杂度需手动处理新增/删除属性自动处理所有操作

4. 应用场景

Object.defineProperty
  • 兼容性要求高:需支持旧浏览器(如 IE)。
  • 简单数据劫持:已知属性的监听场景(如 Vue 2 的响应式系统)。
Proxy
  • 现代浏览器项目:如 Vue 3、React 新特性。
  • 复杂监听需求:需监听属性新增、删除或数组变化。
  • 库/框架开发:提供更灵活的数据劫持能力。

5. 进阶示例

Proxy 实现深度监听
function reactive(obj) {
  return new Proxy(obj, {
    get(target, prop) {
      const value = Reflect.get(target, prop);
      // 递归代理嵌套对象
      return typeof value === 'object' ? reactive(value) : value;
    },
    set(target, prop, value) {
      console.log(`更新 ${prop}`);
      return Reflect.set(target, prop, value);
    }
  });
}

const data = reactive({ user: { name: 'Alice' } });
data.user.name = 'Bob'; // 输出: "更新 name"

6. 总结

  • Object.defineProperty:适合已知属性的简单劫持,兼容性好,但功能有限。
  • Proxy:功能强大,适合现代项目,能全面监听对象变化,是未来趋势。
  • 实际选择:根据项目需求(兼容性、功能复杂度)决定使用哪种方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值