标签
note
字数
691 字
阅读时间
3 分钟
defineProperty 也是可以监听到数组变化的
Object.defineProperty 在数组中的表现和在对象中的表现是一致的,数组的索引就可以看做是对象中的 key。
- 通过索引访问或设置对应元素的值时,可以触发
getter和setter方法 - 通过
push或unshift会增加索引,对于新增加的属性,需要再手动初始化才能被observe。 - 通过
pop或shift删除元素,会删除并更新索引,也会触发setter和getter方法。
所以,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表示不背这个锅 - 掘金