MST

星途 面试题库

面试题:Vue从Object.defineProperty切换到Proxy带来的性能优化

从性能优化的角度分析,Vue在响应式系统中从Object.defineProperty演进到Proxy,在数据劫持、依赖收集与更新等方面有哪些显著的提升?
33.4万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

数据劫持

  • Object.defineProperty
    • 只能对对象的已有属性进行劫持,对于新增属性需要手动调用 Vue.$set 才能使之变为响应式。例如在一个对象 data = {name: 'John'} 中,如果后续添加 data.age = 20,默认不会触发视图更新。
    • 劫持的是对象的属性,深度监听需要递归处理,性能消耗较大。当对象嵌套层次很深时,递归遍历每个属性并使用 Object.defineProperty 进行劫持,会增加初始化的性能开销。
  • Proxy
    • 可以直接对整个对象进行代理,无需关心对象属性的增减,对新增属性和删除属性都能直接监听。例如 const data = new Proxy({}, {}),后续对该代理对象添加或删除属性都能被监听到。
    • 无需递归监听,代理对象可以直接处理整个对象的操作,在处理深层嵌套对象时性能更优。比如对于 {a: {b: {c: 1}}} 这样的深层对象,使用Proxy监听更高效。

依赖收集与更新

  • Object.defineProperty
    • 依赖收集的粒度是属性级别的,在数据更新时,即使只是对象中的一个小部分发生变化,也可能会导致整个组件重新渲染。例如对象 {name: 'John', age: 20} 中,name 属性变化,可能会使依赖该对象的整个组件重新渲染。
    • 对于数组,通过重写数组的变异方法(如 pushpop 等)来实现依赖收集与更新,实现相对复杂且不够灵活。
  • Proxy
    • 依赖收集可以基于整个对象,能够更精准地控制更新范围,减少不必要的重新渲染。例如对象某个属性变化时,Proxy能更准确判断哪些部分依赖了该变化,从而只更新相关部分。
    • 对数组的监听更加自然,不需要像 Object.defineProperty 那样重写数组方法,Proxy可以直接监听数组的变化,在处理数组相关的依赖收集和更新时更简洁高效。