Vue响应式原理中, Object.definePropty有什么缺陷?为什么在Vue3.0采用了Proxy,抛弃了Object.definePropty?
Object.definePropty
该方法允许精确地添加或修改对象的属性,并返回对象。默认情况下此方法添加的属性是不可修改的。
用法:
Object.definePropty(obj,prop,descriptor)返回值:返回更新或者添加属性后的obj对象。
参数:
obj:要定义属性的对象。prop:要添加或修改的属性名。descriptor:属性描述符对象。包含以下属性的对象:
value:属性的值,默认值是undefinedwritable:属性是否可写。默认值是falseenumerable:属性的可枚举性,默认值是false,即属性不可枚举(或者说目标属性在 for…in、Object.keys、JSON.stringify 中是否可遍历)。configurable:属性的可配置性。默认为false,即属性不可被删除。get:获取属性值的函数。set:设置属性值的函数。
注意:
Object.defineProperty设置了getter和setter之后,就不能设置value属性。否则报错:
Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute,
Proxy
Proxy对象创建一个对象的代理,从而实现基本操作的拦截和自定义。
用法:
const _my_proxy = new Proxy(target,handler)参数:
target:需要被代理的对象。通常是引用数据类型(数组,函数,对象等)。handler:一个配置对象,具有以下配置选项。handler.apply()
handler.construct()
handler.defineProperty()
handler.deleteProperty()
handler.get() 拦截对象属性的读写操作。
handler.getOwnPropertyDescriptor()
handler.getPrototypeOf()
handler.has() 拦截
in操作符,判断对象是否包含某个属性。handler.isExtensible()
handler.ownKeys()
handler.preventExtensions()
handler.set() 拦截对象属性的赋值操作。
handler.setPrototypeOf()
Object.definePropty有什么缺陷?
- 无法监听数组的变化。
- 无法监听对象属性的添加或删除
- 性能问题:这个api需要递归遍历对象的所有属性并为其添加
getter和setter,者在对象负责或者嵌套层级较深时会影响性能。
Proxy的优势
- 全面监听对象和数组
- 性能提升:Proxy在对象层级较深时,只在访问属性时才会进行代理,性能更好。
Vue 3.0采用Proxy替代Object.defineProperty,主要因为Proxy能更全面、高效地监听对象和数组的变化,解决了Object.defineProperty在数组监听、属性增删和性能上的缺陷,同时提供了更好的扩展性和兼容性。