实际上,实现响应式数据要比想象中难很多,并不是单纯地拦截get/set 操作即可。举例来说,如何拦截 for…in 循环?track 函数如何追踪拦截到的 for…in 循环?类似的问题还有很多。除此之外,我们还应该考虑如何对数组进行代理。Vue.js 3 还支持集合类型,如 Map、Set、WeakMap 以及 WeakSet 等,那么应该如何对集合类型进行代理呢?实际上,想要实现完善的响应式数据,我们需要深入语言规范。本章在揭晓答案的同时,也会从语言规范的层面来分析原因,让你对响应式数据有更深入的理解。
本帖引用 ECMA-262 规范,如不作特殊说明,皆指该规范的 2021 版本。
1、理解 Proxy 和 Reflect
既然 Vue.js 3 的响应式数据是基于 Proxy 实现的,那么我们就有必要了解 Proxy 以及与之相关联的 Reflect。什么是 Proxy 呢?简单地说,使用Proxy 可以创建一个代理对象。它能够实现对其他对象的代理,这里的关键词是其他对象,也就是说,Proxy 只能代理对象,无法代理非对象值,例如字符串、布尔值等。那么,代理指的是什么呢?所谓代理,指的是对一个对象基本语义的代理。它允许我们拦截并重新定义对一个对象的基本操作。这句话的关键词比较多,我们逐一解释。