Skip to content
标签
note
字数
691 字
阅读时间
3 分钟

defineProperty 也是可以监听到数组变化的

Object.defineProperty 在数组中的表现和在对象中的表现是一致的,数组的索引就可以看做是对象中的 key

  1. 通过索引访问或设置对应元素的值时,可以触发 gettersetter 方法
  2. 通过 pushunshift 会增加索引,对于新增加的属性,需要再手动初始化才能被 observe
  3. 通过 popshift 删除元素,会删除并更新索引,也会触发 settergetter 方法。

所以,Object.defineProperty 是有监控数组下标变化的能力的,只是 vue2.x 放弃了这个特性

  • 一方面是需要遍历数组每个元素进行监听
  • 另一方面,如果数组出现新增元素,还需要重新遍历添加监听

defineProperty 和 proxy 区别

1. Object.defineProperty 只能劫持对象的属性,而 Proxy 是直接代理对象

由于 Object.defineProperty 只能对属性进行劫持,需要遍历对象的每个属性。而 Proxy 可以直接代理对象。

2. Object.defineProperty 对新增属性需要手动进行 Observe

由于 Object.defineProperty 劫持的是对象的属性,所以新增属性时,需要重新遍历对象,对其新增属性再使用 Object.defineProperty 进行劫持。

也正是因为这个原因,使用 vue 给 data 中的数组或对象新增属性时,需要使用 vm.$set 才能保证新增的属性也是响应式的。

$set 方法

set 方法中,对 target 是数组和对象做了分别的处理,target 是数组时,会调用重写过的 splice 方法进行手动 Observe

对于对象,如果 key 本来就是对象的属性,则直接修改值触发更新,否则调用 defineReactive 方法重新定义响应式对象。

Proxy 优缺点

优点

  • 相比于 defineProperty,对数组或者对象的改变监听更为友好完善
  • Proxy 作为新标准,长远来看,JS 引擎会继续优化 Proxy ,但 getter 和 setter 基本不会再有针对性优化

缺点

兼容性差

可以看到,Proxy 对于 IE 浏览器来说简直是灾难。

并且目前并没有一个完整支持 Proxy 所有拦截方法的 Polyfill 方案,有一个 google 编写的 proxy-polyfill 也只支持了 get,set,apply,construct 四种拦截,可以支持到 IE9+ 和 Safari 6+。

![[面试前助记小手册#响应式原理分析]]

参考

为什么Vue3.0使用Proxy实现数据监听?defineProperty表示不背这个锅 - 掘金

贡献者

The avatar of contributor named as jiechen jiechen
The avatar of contributor named as chenjie chenjie

页面历史

撰写