CodeWalk

Vue3 Proxy响应式与defineProperty对比

作者:屠龙少年 · 2026-05-30 12:55

对比Vue2使用Object.defineProperty和Vue3使用Proxy实现响应式的差异。Proxy解决了defineProperty哪些无法解决的问题?Vue3响应式在性能上有哪些提升?

回答

屠龙少年

Object.defineProperty的限制(Vue2)

  1. 无法检测新增属性this.obj.newKey = 'value'非响应式
    • 需使用Vue.set(obj, 'key', value)
  2. 无法检测数组索引修改arr[0] = newVal不触发更新
    • Vue2重写数组方法(push/pop/splice等),但直接索引赋值不行
  3. 无法检测数组长度变化arr.length = 0不触发
  4. 需要递归遍历:初始化时递归所有属性,对象越大初始化越慢
  5. 新增/删除需要额外APIVue.set/Vue.delete

Proxy的优势(Vue3)

  1. 拦截所有操作:get/set/has/deleteProperty/ownKeys等13种trap
    const proxy = new Proxy(target, {
      get(target, key, receiver) {
        track(target, key);  // 依赖收集
        return Reflect.get(target, key, receiver);
      },
      set(target, key, value, receiver) {
        const result = Reflect.set(target, key, value, receiver);
        trigger(target, key);  // 触发更新
        return result;
      }
    });
    
  2. 动态属性响应式:新增/删除属性自动触发
  3. 完整数组支持:索引修改、长度变化自动检测
  4. Map/Set/WeakMap/WeakSet支持
  5. 懒响应式(惰性代理):访问时才代理嵌套对象,而非递归

性能提升

  1. 初始化更快:Proxy无需递归遍历所有属性,只在访问时惰性代理
  2. 内存占用更小:不需要为每个属性存储dep实例
  3. 运行时更高效:跳过不必要的遍历

缺点对比

  • Proxy无法polyfill(IE11不支持)
  • Proxy特殊对象处理更复杂(如内置对象Date、RegExp)
  • Proxy在极个别场景性能略低于defineProperty(但可忽略不计)