在Vue2和3 中 defineProperty 和 Proxy 都是用来实现响应式数据绑定的。实现的性能相似,然而两个API却有着实质的区别。

  1. 监听数据的角度

    1. defineproperty只能监听某个属性而不能监听整个对象。
    2. proxy不必设置具体属性,间接监听整个对象。
    3. defineproperty监听须要晓得是哪个对象的哪个属性,而proxy只须要晓得哪个对象就能够了。也就是会省去for in循环进步了效率。
  2. 监听对原对象的影响

    1. 因为defineproperty是通过在原对象身上新增或批改属性减少描述符的形式实现的监听成果,肯定会批改原数据。
    2. proxy只是原对象的代理,proxy会返回一个代理对象不会在原对象上进行改变,对原数据无污染。
  3. 实现对数组的监听

    1. 因为数组 length 的特殊性 (length 的描述符configurable 和 enumerable 为 false,并且妄图批改 configurable 为 True 的话 js 会间接报错:VM305:1 Uncaught TypeError: Cannot redefine property: length)
    2. defineproperty无奈监听数组长度变动, Vue只能通过重写数组办法的形式变现达成监听的成果,光重写数组办法还是不能解决批改数组下标时监听的问题,只能再应用自定义的$set的形式
    3. proxy因为本身个性,是创立新的代理对象而不是在原数据身上监听属性,对代理对象进行操作时,所有的操作都会被捕获,包含数组的办法和length操作,再不须要重写数组办法和自定义set函数了。(代码示例在下方)

    4. 监听的范畴

    1. defineproperty只能监听到valueget set 变动。
    2. 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等操作都被捕获了