Vue2源码【7】数据劫持使用Proxy的优势

Proxy,与其说是代理,还不如说代理是基于拦截的,在功能定位上,和defineProperty是不一样的。只是恰好Proxy覆盖了defineProperty的getter和setter两个api。

导论 #要看看

vue双向绑定也依靠数据劫持:引用前文:能实现双向绑定的方式有很多,比如ng就是脏值检测,而vue还是数据劫持。KnockoutJS基于观察者模式的双向绑定,Ember基于数据模型的双向绑定。

  • 所谓数据劫持,指的是在访问或者修改对象的某个属性时,通过一段代码拦截这个行为,进行额外的操作或者修改返回结果。
    • 比较典型的是 Object.defineProperty()
    • ES6 中新增的 Proxy 对象。
    • 【可忽略】另外还有已经被废弃的 Object.observe(),废弃的原因正是 Proxy 的出现,因此这里我们就不继续讨论这个已经被浏览器删除的方法了。用Proxy实现Object.obserse的效果

Proxy和Reflect 在数据劫持方面的知识 #作为基础

  • (首先,Reflect的API和Proxy的是对应的,这不是偶然,在js里面,Reflect就是Proxy的一个小跟班)
  • Reflect :和其他语言中的Reflect“被提出的意义”有点不同
    • 提出原因: Reflect 的主要作用就是当你拦截重写这些方法的时候,让你能够很方便调用原方法Reflect.xxxx(...arguments)。js 语言内置的 Reflect 对象上的函数是为 Proxy 准备的,Proxy 的 handler 的各种 trap 分别对应 Reflect 上的同名方法。(这也是为什么与 Proxy 无关的反射相关特性将不会放到 Reflect 对象上。) 来自知乎hex大佬
    • 特点1: 把对象方法和对象解耦。把对象操作都变成了函数式。
    • 特点2: 填补Object API的不合理设计。以前抛出异常的操作,变成返回false。

评价vue2数据劫持这种方式 主要 vs reflect: 更健全更强大的拦截

  • Proxy,与其说是代理,还不如说代理是基于拦截的,在功能定位上,和defineProperty是不一样的。只是恰好Proxy覆盖了defineProperty的getter和setter两个api。
    • 我们可以这样认为,Proxy提供比较健全的拦截机制
    • 问:Proxy 也是需要递归遍历的吧,它只能代理一层对象? 答:需要。但是不需要一开始就递归遍历,啥时候触发了深层对象的getter,啥时候对它进行一次 observed 即可。 via

Object.defineProperty的缺点: 劫持机制不太完整:

  • 1 拦截数组的变化不太方便
    • 拦截直接修改数组元素:因为性能而在vue中放弃实现 只是性能问题
    • defineProperty无法监听push等数组方法:hack方法就是“数组变异”:本质,还是需要重写这些方法
  • 2 (get和set)劫持的是 对象的属性, 而不是整个对象。

以上缺点,Proxy都没有。

Proxy的缺陷:

1 浏览器支持不足,IE全军覆没。

文章目录
  1. 导论 #要看看
  2. Proxy和Reflect 在数据劫持方面的知识 #作为基础
  3. 评价vue2数据劫持这种方式 主要 vs reflect: 更健全更强大的拦截