请问,采用 Object.defineProperty 实现数据劫持时,存在哪些缺陷或不足之处?
考察说明
考察对Vue 2响应式原理中Object.defineProperty局限性的理解
回答思路
- 【回答框架 1】Object.defineProperty是ES5提供的方法,Vue 2用它重写getter和setter来劫持属性读取和赋值,从而实现响应式。它的第一个核心缺陷是无法追踪属性的新增和删除,因为劫持是针对已有属性,动态添加的属性不会成为响应式,Vue为此提供了Vue.set和Vue.delete来弥补,但无法直接检测索引赋值和修改数组长度。
- 【回答框架 2】第二个缺陷是对数组的支持有限,Vue 2只能拦截数组的七种变更方法(push、pop、shift、unshift、splice、sort、reverse),而通过索引直接修改数组元素(如arr[0]=1)不会触发响应,需要替换整个数组或使用Vue.set。
- 【回答框架 3】第三个缺陷是需要递归遍历对象的所有属性来定义响应式,对于深层嵌套对象性能开销大,且必须在初始化时就完成劫持,之后新增的属性需要额外处理,这也导致初始化速度慢,大型对象可能卡顿。
- 【回答框架 4】在ES6的Proxy出现后,可以代理整个对象,拦截更多操作(如属性添加、删除、in、hasOwnProperty等),且对数组有更好的支持,Vue 3因此改用Proxy,解决了Object.defineProperty的上述缺陷。
- 【关键点 1】无法检测对象属性的添加和删除
- 【关键点 2】对数组有效性的限制,只能监听七个方法
- 【关键点 3】需要递归遍历对象,性能有开销且初始化慢
- 【易错点 1】不要宣称Object.defineProperty完全无法监听数组,实际上能监听数组方法变更
- 【易错点 2】需注意Vue.set是Vue 2的补救方案,并非Object.defineProperty自带能力