Skip to content

Vue响应式原理中, Object.definePropty有什么缺陷?为什么在Vue3.0采用了Proxy,抛弃了Object.definePropty?

Object.definePropty

该方法允许精确地添加或修改对象的属性,并返回对象。默认情况下此方法添加的属性是不可修改的。

用法:

typescript
Object.definePropty(obj,prop,descriptor)

返回值:返回更新或者添加属性后的obj对象。

参数:

  • obj:要定义属性的对象。

  • prop:要添加或修改的属性名。

  • descriptor:属性描述符对象。

    包含以下属性的对象:

    value:属性的值,默认值是undefined

    writable:属性是否可写。默认值是false

    enumerable:属性的可枚举性,默认值是false,即属性不可枚举(或者说目标属性在 for…in、Object.keys、JSON.stringify 中是否可遍历)。

    configurable:属性的可配置性。默认为false,即属性不可被删除。

    get:获取属性值的函数。

    set:设置属性值的函数。

注意:

Object.defineProperty设置了gettersetter之后,就不能设置value属性。否则报错:

Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute,

Proxy

Proxy对象创建一个对象的代理,从而实现基本操作的拦截和自定义。

用法:

typescript
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有什么缺陷?

  1. 无法监听数组的变化。
  2. 无法监听对象属性的添加或删除
  3. 性能问题:这个api需要递归遍历对象的所有属性并为其添加gettersetter,者在对象负责或者嵌套层级较深时会影响性能。

Proxy的优势

  1. 全面监听对象和数组
  2. 性能提升:Proxy在对象层级较深时,只在访问属性时才会进行代理,性能更好。

Vue 3.0采用Proxy替代Object.defineProperty,主要因为Proxy能更全面、高效地监听对象和数组的变化,解决了Object.defineProperty在数组监听、属性增删和性能上的缺陷,同时提供了更好的扩展性和兼容性。

Last updated: