Object.defineProperty vs Proxy 对比总结

Object.defineProperty vs Proxy 对比总结

一、基本区别

特性 Object.defineProperty Proxy
出现时间 ES5 (2009) ES6 (2015)
监听范围 单个属性 整个对象
API复杂度 较复杂 更简洁
性能 较好 稍差(但可接受)
浏览器支持 几乎全部 IE不支持

二、核心能力对比

1. 监听范围

javascript 复制代码
// defineProperty - 需要逐个属性定义
const obj = { name: '张三', age: 18 }
Object.defineProperty(obj, 'name', { get() {...}, set() {...} })
Object.defineProperty(obj, 'age', { get() {...}, set() {...} })
// 新增属性无法监听

// Proxy - 监听整个对象
const proxy = new Proxy(obj, {
    get(target, key) {...},
    set(target, key, value) {...}
})
// 所有属性(包括新增)都能监听

2. 数组监听

javascript 复制代码
// defineProperty - 无法直接监听数组变化
const arr = [1, 2, 3]
// 需要重写数组方法才能实现

// Proxy - 完美支持数组
const proxyArr = new Proxy(arr, {
    set(target, key, value) {
        console.log(`设置索引${key}: ${value}`)
        target[key] = value
        return true
    }
})
proxyArr.push(4) // 可以监听到

3. 嵌套监听

javascript 复制代码
// defineProperty - 需要递归遍历
function observe(obj) {
    Object.keys(obj).forEach(key => {
        if (typeof obj[key] === 'object') {
            observe(obj[key]) // 递归
        }
        defineReactive(obj, key)
    })
}

// Proxy - 惰性代理
const proxy = new Proxy(obj, {
    get(target, key) {
        const val = target[key]
        // 只在访问时才代理对象
        if (typeof val === 'object') {
            return new Proxy(val, handler)
        }
        return val
    }
})

三、功能对比

功能 defineProperty Proxy
监听属性读取 ✅ get ✅ get
监听属性赋值 ✅ set ✅ set
监听属性删除 ✅ deleteProperty
监听函数调用 ✅ apply
监听构造函数 ✅ construct
监听in操作符 ✅ has
监听for...in ✅ ownKeys
监听属性定义 ✅ defineProperty

四、实际代码对比

Vue 2 vs Vue 3 响应式

javascript 复制代码
// Vue 2 - defineProperty
function defineReactive(obj, key, val) {
    Object.defineProperty(obj, key, {
        get() {
            console.log(`获取${key}: ${val}`)
            return val
        },
        set(newVal) {
            console.log(`设置${key}: ${newVal}`)
            val = newVal
        }
    })
}

// Vue 3 - Proxy
const reactive = (target) => {
    return new Proxy(target, {
        get(target, key, receiver) {
            const res = Reflect.get(target, key, receiver)
            console.log(`获取${String(key)}`)
            return res
        },
        set(target, key, value, receiver) {
            const res = Reflect.set(target, key, value, receiver)
            console.log(`设置${String(key)}: ${value}`)
            return res
        }
    })
}

五、优缺点总结

Object.defineProperty

优点:

  • 性能较好
  • 兼容性好(IE9+)
  • 可精确控制单个属性

缺点:

  • 无法监听数组变化(需要hack)
  • 无法监听新增/删除属性
  • 需要递归遍历对象
  • API不够直观

Proxy

优点:

  • 监听能力强(13种拦截器)
  • 支持数组、对象新增属性
  • 无需递归(惰性代理)
  • API更简洁
  • 可以代理多种数据结构

缺点:

  • 兼容性稍差(无IE)
  • 性能略低于defineProperty
  • 无法polyfill完全

六、使用场景建议

场景 推荐方案 原因
简单对象监听 defineProperty 性能好,足够用
复杂响应式系统 Proxy 功能强大,维护简单
需要兼容IE defineProperty Proxy不支持IE
数组操作监听 Proxy defineProperty需要hack
动态属性监听 Proxy defineProperty无法监听新增属性
性能敏感场景 defineProperty 执行效率更高

七、最佳实践示例

javascript 复制代码
// 简单属性监听 - 用defineProperty
const formData = {}
Object.defineProperty(formData, 'username', {
    set(val) {
        console.log('输入验证:', val)
        this._username = val
    }
})

// 复杂响应式 - 用Proxy
const reactive = (obj) => {
    return new Proxy(obj, {
        get(target, key) {
            if (typeof target[key] === 'object') {
                return reactive(target[key]) // 递归代理
            }
            return Reflect.get(target, key)
        },
        set(target, key, value) {
            console.log(`更新视图: ${key}=${value}`)
            return Reflect.set(target, key, value)
        }
    })
}

总结

  • defineProperty:简单、性能好、兼容性强,但功能受限
  • Proxy:强大、灵活、语义清晰,但需要现代浏览器

Vue 3 选择 Proxy 是因为它能更好地处理动态属性、数组等复杂场景,代码更简洁。如果不需要兼容IE,Proxy是更好的选择。

相关推荐
球球不吃虾几秒前
Nuxt在使用过程中的一些小总结(二)
前端·vue·nuxt
2601_958352903 小时前
A-59U 仅 37mm 却集成 USB + 双波束?
前端·回声消除·语音模块·降噪处理·降噪消回音
泯泷9 小时前
那段文字是谁删的?Yjs 14 正式版之前,一套删除归属方案的实现与边界
前端·javascript·算法
野槐11 小时前
前端项目优化(有了我,会发生...)
前端
aa小小12 小时前
【无标题】
前端
计算机魔术师13 小时前
还在单线程跟 AI 聊天?Claude Code 并行多会话让你一个人干三个人的活
前端
志尊宝13 小时前
Vue3 零基础每日笔记(038):亲手封装 useDebounceFn 与 useThrottleFn——高频事件的流量阀
前端·javascript·vue·html·vue3
JavaGuide13 小时前
对标 MinIO!全新一代分布式文件系统正式发布
前端·后端
风骏时光牛马13 小时前
AI驱动自动化业务工作流搭建实践
前端
码云之上14 小时前
Skill 里的脚本终于能跑了,星悟接 CubeSandbox 的纪实
前端·人工智能·前端框架