object defineproperty 和 Proxy的对比

好问题!简单直接地说:

Object.definePropertyProxy 都可以用来拦截或控制对象的读写操作,但他们的能力、使用场景、灵活性差别蛮大的。

下面我帮你一条条对比清楚:


特性 Object.defineProperty Proxy
作用对象 直接在对象的单个属性上定义 getter/setter 可以拦截整个对象的所有操作
可拦截的操作 只限于属性的读取和赋值 几乎可以拦截所有操作(读、写、删、in、for...in 等)
适用粒度 单个属性 整个对象
语法复杂度 需要一个个属性去定义 一次性定义统一的处理逻辑
动态新增属性拦截 不支持(新增的属性不会自动带 getter/setter) 支持(拦截所有属性访问,包括动态新增)
兼容性 非常好,ES5 支持 较差,需 ES6+,低版本浏览器需要 polyfill 或降级处理
使用场景 小范围精确控制,如数据响应(早期的 Vue 2.x) 大范围监控,比如数据代理、观察、封装库(Vue 3)

举个小例子:

Object.defineProperty

const obj = {};
Object.defineProperty(obj, 'name', {
  get() {
    console.log('访问 name');
    return '小明';
  },
  set(value) {
    console.log('设置 name 为', value);
  }
});

obj.name;  // 访问 name
obj.name = '小红';  // 设置 name 为 小红
obj.age =10 // no 
  • ➔ 只能对 name 这个属性起作用
  • ➔ 不能动态监听后续加进来的其他属性

Proxy

const obj = {};
const proxyObj = new Proxy(obj, {
  get(target, key) {
    console.log(`访问属性 ${key}`);
    return target[key];
  },
  set(target, key, value) {
    console.log(`设置属性 ${key} 为 ${value}`);
    target[key] = value;
    return true;
  }
});

proxyObj.name;  // 访问属性 name
proxyObj.age = 18;  // 设置属性 age 为 18
  • ➔ 不管访问哪个属性,都能被统一拦截
  • ➔ 支持监听新增的属性
  • ➔ 能做更复杂的操作,比如验证、字段保护、虚拟属性等

posted @ 2025-04-27 16:11  闲云-野鹤  阅读(40)  评论(0)    收藏  举报