object.defineProperty 和 proxy 的区别

文章类型:Javascript

发布者:hp

发布时间:2025-04-13

一:范围上

1:Object.defineProperty(适用于对单个属性的精细化控制)

只能拦截对象属性的读取(get)和设置(set)。

只能对已知属性进行拦截,无法拦截新增属性或删除属性。

2:Proxy(适用于对整个对象的全面控制)

可以拦截对象的多种操作,包括属性读取(get)、设置(set)、删除(deleteProperty)、枚举(enumerate)、函数调用(apply)等。

可以拦截未知属性的操作,支持动态属性的拦截。

二:使用方式上

1:Object.defineProperty

需要针对每个属性单独设置拦截器。

修改对象的现有行为,而不是创建一个新对象

2:Proxy

创建一个代理对象,拦截对目标对象的所有操作。

不修改原对象,而是返回一个新的代理对象

三:拦截操作上

1:Object.defineProperty

仅支持 get 和 set 拦截。无法拦截以下操作:属性的删除(delete)。属性的枚举(for...in 或 Object.keys)。新增属性。

2:Proxy

支持多种操作的拦截,包括:get:读取属性。set:设置属性。deleteProperty:删除属性。has:in 操作符。ownKeys:Object.keys、for...in 等。apply:函数调用(当代理目标是函数时)。

四:性能上

1:Object.defineProperty

性能较好,适合对少量属性进行拦截。

但如果需要对大量属性进行拦截,代码会变得冗长且难以维护

2:Proxy

性能略低于 Object.defineProperty,因为需要处理更多的拦截操作。

但在需要拦截多种操作或动态属性的场景下,Proxy 的性能优势更明显

五:代码上

1:Object.defineProperty

const obj = {};
Object.defineProperty(obj, 'name', {
  get() {
    console.log('读取 name 属性');
    return this._name;
  },
  set(value) {
    console.log('设置 name 属性');
    this._name = value;
  },
});
obj.name = 'Alice'; // 设置 name 属性
console.log(obj.name); // 读取 name 属性

2:Proxy

const target = {};
const proxy = new Proxy(target, {
  get(obj, prop) {
    console.log(`读取 ${prop} 属性`);
    return obj[prop];
  },
  set(obj, prop, value) {
    console.log(`设置 ${prop} 属性`);
    obj[prop] = value;
    return true;
  },
});
proxy.name = 'Alice'; // 设置 name 属性
console.log(proxy.name); // 读取 name 属性