proxy与Object.defineProperty()对比

1、proxy和Object.defineProperty()是什么?

代理对象是用于定义基本操作的自定义行为(例如,属性查找,赋值,枚举,函数调用等),换句话说,我们可以说代理对象是我们的目标对象的包装器,我们可以在其中操纵其属性并阻止对它的直接访问,也就是不让你直接操作对象或者数组等,可以进行数据劫持(定义:在访问或者修改对象的某个属性时,通过一段代码拦截这个行为,进行额外的操作或者修改返回结果.数据劫持最典型的应用—双向的数据绑定)

2、proxy和Object.defineProperty()用来干什么?

主要是为了实现双向数据绑定,双向数据绑定就是数据变动,需要得到一个反馈,那普通的对象和数组变动,怎么会反馈给你东西呢?肯定需要一个中间“拦截器”来反馈,数据变动后,proxy会反馈一个结果出来,你拿到这个结果再去做你想做的事

  1. Vue 2.x 利用 Object.defineProperty(),并且把内部解耦为 Observer, Dep, 并使用 Watcher 相连
  2. Vue 在 3.x 版本之后改用 Proxy 进行实现

3、proxy相对于Object.defineProperty()的好处

Object.defineProperty() 的问题主要有三个:

  • 不能监听数组的变化
  • 必须遍历对象的每个属性
  • 必须深层遍历嵌套的对象

proxy可以支持:

  • 数组监听
  • 对象整体监听,不需要遍历每一个属性

4、proxy主要的三个方法

get()

get方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选。
get方法的用法,上文已经有一个例子,下面是另一个拦截读取操作的例子
在这里插入图片描述

上面代码表示,如果访问目标对象不存在的属性,会抛出一个错误。如果没有这个拦截函数,访问不存在的属性,只会返回undefined

set()

set方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。
假定Person对象有一个age属性,该属性应该是一个不大于 200 的整数,那么可以使用Proxy保证age的属性值符合要求。
在这里插入图片描述

上面代码中,由于设置了存值函数set,任何不符合要求的age属性赋值,都会抛出一个错误,这是数据验证的一种实现方法。利用set方法,还可以数据绑定,即每当对象发生变化时,会自动更新 DOM

deleteProperty() §

deleteProperty方法用于拦截delete操作,如果这个方法抛出错误或者返回false,当前属性就无法被delete命令删除。
在这里插入图片描述

上面代码中,deleteProperty方法拦截了delete操作符,删除第一个字符为下划线的属性会报错。
注意,目标对象自身的不可配置(configurable)的属性,不能被deleteProperty方法删除,否则报错。

5、使用Proxy实现简单的vue双向绑定

vue3.x使用了Proxy来对数据进行监听了,因此我们来简单的来学习下使用Proxy来实现一个简单的vue双向绑定。
我们都知道实现数据双向绑定,需要实现如下几点:

  1. 需要实现一个数据监听器 Observer, 能够对所有数据进行监听,如果有数据变动的话,拿到最新的值并通知订阅者Watcher.
  2. 需要实现一个指令解析器Compile,它能够对每个元素的指令进行扫描和解析,根据指令模板替换数据,以及绑定相对应的函数。
  3. 需要实现一个Watcher, 它是链接Observer和Compile的桥梁,它能够订阅并收到每个属性变动的通知,然后会执行指令绑定的相对应
    的回调函数,从而更新视图。
    下面是一个简单的demo源码如下(我们可以参考下,理解下原理):
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_53334387/article/details/127207903