Object.defineProperty和Proxy

区别

Object.defineProperty和Proxy都可以用于实现对象的响应式,但它们有一些区别:

  1. 语法和使用方式:
  • Object.defineProperty需要对对象的每个属性进行单独定义,并且需要指定get和set函数来实现属性的拦截。
  • Proxy可以直接对整个对象进行代理,并通过拦截器(handler)定义对对象的各种操作,包括get、set、delete、has等。
  1. 监听粒度:
  • Object.defineProperty只能监听对象的属性,无法监听整个对象或数组的变化。
  • Proxy可以监听对象的整个变化,包括属性的增加、删除和修改,以及数组的变化(push、pop、shift、unshift等)。
  1. 兼容性:
  • Object.defineProperty支持IE9及以上的现代浏览器。
  • Proxy不支持IE浏览器(除了Edge),只能在较新的现代浏览器中使用。但可以通过使用polyfill来实现对不支持Proxy的浏览器进行兼容。
  1. 性能:
  • Object.defineProperty的性能相对较差,因为每个属性都需要单独定义,而且无法监听整个对象或数组的变化。
  • Proxy的性能相对较好,因为它可以一次性对整个对象进行代理,并可以监听整个对象的变化。

综上所述,Proxy比Object.defineProperty更为强大和灵活,推荐在新项目中使用Proxy来实现对象的响应式。如果需要兼容老旧的浏览器,可以考虑使用Object.defineProperty,并配合一些辅助工具来实现类似的功能。

Object.defineProperty实现响应式

可以使用Object.defineProperty来实现一个简单的响应式系统,通过监听对象的所有属性并在属性值发生变化时触发回调函数。

/**
 * 使用Object.defineProperty实现一个简单的响应式
 * @param data 监听的对象
 */
const defineReactiveByProperty = (data) => {
  for (let [key, value] of Object.entries(data)) {
    Object.defineProperty(data, key, {
      enumerable: true, // 可枚举
      configurable: true, // 可配置
      // 读取属性值时触发的函数
      get() {
        console.log(`读取属性${key}: ${value}`);
        return value;
      },
      // 设置属性值时触发的函数
      set(newValue) {
        console.log(`设置属性${key}为: ${newValue}`);
        value = newValue;
      },
    });
  }
  return data;
};

// 测试数据
const propertyData = defineReactiveByProperty({
  name: "Alice",
  age: 30,
});

propertyData.name; // 读取属性name: Alice
propertyData.age; // 读取属性age: 30

propertyData.name = "Bob"; // 设置属性name为: Bob
propertyData.age = 25; // 设置属性age为: 25

Proxy实现响应式

使用ES6的Proxy来实现一个简单的响应式系统,监听对象的所有属性并在属性值发生变化时触发回调函数。与前面的例子相比,Proxy提供了更为灵活和强大的响应式特性。

/**
 * 使用proxy实现一个简单的响应式
 * @param data 监听的对象
 * @param onChange 回调函数
 */
const defineReactiveByProxy = (data, onChange) => {
  return new Proxy(data, {
    // 拦截属性的读取
    get(target, key, receiver) {
      console.log(`读取属性${key}: ${target[key]}`);
      return target[key];
    },
    // 拦截属性的设置
    set(target, key, value, receiver) {
      console.log(`设置属性${key}为: ${value}`);
      target[key] = value;
      // 触发回调函数,通知属性值发生变化
      onChange && onChange(key, value);
      return true;
    },
  });
};
// 测试数据
const proxyData = defineReactiveByProxy(
  {
    name: "Alice",
    age: 30,
  },
  (key, value) => {
    console.log(`属性${key}的值已变为: ${value}`);
  }
);

proxyData.name; // 读取属性name: Alice
proxyData.age; // 读取属性age: 30

proxyData.name = "Bob"; // 设置属性name为: Bob
proxyData.age = 25; // 设置属性age为: 25

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值