在 Vue2 和 3 中 defineProperty 和 Proxy 都是用来实现响应式数据绑定的。实现的性能相似,然而两个 API 却有着实质的区别。
监听数据的角度
defineproperty
只能监听某个属性而不能监听整个对象。proxy
不必设置具体属性,间接监听整个对象。defineproperty
监听须要晓得是哪个对象的哪个属性,而proxy
只须要晓得哪个对象就能够了。也就是会省去for in
循环进步了效率。监听对原对象的影响
- 因为
defineproperty
是通过在原对象身上新增或批改属性减少描述符的形式实现的监听成果,肯定会批改原数据。- 而
proxy
只是原对象的代理,proxy
会返回一个代理对象不会在原对象上进行改变,对原数据无污染。实现对数组的监听
- 因为数组
length
的特殊性(length 的描述符 configurable 和 enumerable 为 false,并且妄图批改 configurable 为 True 的话 js 会间接报错:VM305:1 Uncaught TypeError: Cannot redefine property: length)
defineproperty
无奈监听数组长度变动,Vue
只能通过重写数组办法的形式变现达成监听的成果,光重写数组办法还是不能解决批改数组下标时监听的问题,只能再应用自定义的$set
的形式- 而
proxy
因为本身个性,是创立新的代理对象而不是在原数据身上监听属性,对代理对象进行操作时,所有的操作都会被捕获,包含数组的办法和length
操作,再不须要重写数组办法和自定义set
函数了。(代码示例在下方)4. 监听的范畴
defineproperty
只能监听到value
的get set
变动。proxy
能够监听除[[getOwnPropertyNames]]
以外所有JS
的对象操作。(链接看下方)监听的范畴更大更全面。
点击查看 proxy 反对监听的对象操作方法(除 getOwnPropertyNames)
Proxy 监听数组变动示例:
let array = ['1', '2']
let arrayProxy = new Proxy(array, {get(target, key) {console.log('(key:', key + ") 产生了 get 操作")
return target[key]
},
set(target, key, value) {console.log('(key:', key + ") 产生了 set 操作, value=" + value)
return target[key] = value
}
})
arrayProxy.push('我是 push 函数 push 到数组中的值')
// (key: push) 产生了 get 操作
// (key: length) 产生了 get 操作
// (key: 2) 产生了 set 操作, value= 我是 push 函数 push 到数组中的值
// (key: length) 产生了 set 操作, value= 3
// 从 log 能够看出 push length 等操作都被捕获了