简介
在前两篇文章中分别介绍了Object.defineProperty
和Proxy
两个新的特性,其实看起来Proxy
更像是对Object.defineProperty
的一种补充和完善(个人见解)。当然不是说Object.defineProperty
很差,感觉更像是一开始的定位是为了处理对象的特定属性,但是在Vue
等等框架的中被用来劫持整个对象属性,所以后面就出来了Proxy
,更强大的劫持功能。
优缺点
根据上面两篇文章的介绍,大致优缺点如下:
Proxy 相对于 defineProperty 的优点
- 对于对象已有属性:
Object.defineProperty
只能劫持对象的单个属性,如果想劫持整个对象就要循环递归调用Object.defineProperty
。而Proxy
拦截整个对象,并且返回一下新的对象。 - 对于对象新增属性:
Proxy
劫持整个对象,对于新增的属性自动拦截。而Object.defineProperty
需要重新劫持新增的属性 - 对于数组操作:
Object.defineProperty
无法监控到数组下标的变化。而Proxy
可以监听数组变化。 - 拦截或劫持方法:
Object.defineProperty
描述符基本上分为两类数据描述符、存取描述符、通用描述符三种。而Proxy
中有13种traps方法供你选择。 - 是否支持取消劫持:
Object.defineProperty
如果想取消劫持,只能重写描述符,但是configurable: false时就不能重写描述符了。而Proxy
可以通过Proxy.revocable
返回一个可取消的Proxy
实例。 - 浏览器对劫持或拦截的支持:
Proxy
在后续应该会有更好的支持,不然Vue
也不会修改核心代码。 - 性能:
Proxy
性能是比Object.defineProperty
高的,在多个对象属性中。
Proxy 相对于 defineProperty 的缺点
this指向
:defineProperty
因为只绑定对象的属性,一般不会涉及到this问题
。而Proxy
返回的对象的this
和target
的this
不相同。使用难度
: 相对于Proxy
的api,反而defineProperty
上手更容易。
Proxy 和 defineProperty 的一些注意事项
对象冻结
:无论是defineProperty
、Object.freeze
、Object.seal(密封)
都不是深度冻结,如果想深度冻结只能递归实现。this问题
:Proxy
在使用是要注意this
指向问题。
各自实现双向绑定
现在的三大框架非常的流行,在数据流中分为两派React
的单项数据流,Angluar/Vue
的双向数据流。其实React
也是实现了的双向数据绑定的,只不过要通过setState
来触发。
在不同框架中实现双向数据绑定也是不相同的,大致如下图所示:
Object.defineProperty
和proxy
都是Vue
不同版本的重要组成部分,它们都是可以实现双向绑定中的数据劫持,其实也就是响应式对象,在以前的文章有深入 Vue 系列 Vue 中的响应式对象、
深入 Vue 系列 Vue 中的依赖收集、深入 Vue 系列 Vue 中的派发更新,如果感兴趣的可以去看看。
依照Vue
代码中的双向绑定思路,大致分为以下三步:
- 把普通对象通过
Object.defineProperty
变为响应式对象 - 同时
getter
中收集依赖,也就是渲染wather
- 在
setter
中派发更行
下面写的实例不会这么复杂,当然也会仿照Vue
源码中的mvvm
去写。
Object.defineProperty 实现双向绑定
简单实现
- 劫持对象的
get、set
属性 input
事件更新对象值
1 |
|
1 | // 对象字面量 |
上面这个代码只是简单了实现最简单的效果,在input
中输入代码,同时更新到p
中。