前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库Vue 3 Proxy 和 Vue 2 defineProperty 区别
VuVue响应式原理

Vue 3 的 reactive 为什么改用 Proxy,而不是继续用 Vue 2 的 Object.defineProperty?

Proxy 能拦截对象层面的多种操作,便于覆盖新增、删除与集合访问;响应式仍需要 Vue 的依赖收集和触发机制。

前端进阶之旅 · 一题精讲更新于 2026.09.06
Vue#响应式原理
先看核心答案读代码示例
理解线索

拦截操作只是建立响应式系统的第一步

  1. 拦截捕获读取、写入、删除和枚举等对象操作
  2. 依赖把读取时正在执行的响应式作用与数据关联
  3. 触发写入后识别相关依赖,再由框架安排更新

讲解 Proxy 时应区分语言能力、Vue 的具体实现和应用实际使用约束。

核心回答

先记住这个答案

Object.defineProperty 主要围绕已经定义的属性配置 getter/setter;Vue 2 因此需要为对象已有字段安装访问器,并对数组方法作专门处理,新增、删除和部分数组修改存在额外使用约束。Proxy 面向整个对象提供 get、set、deleteProperty、ownKeys 等拦截点,让 Vue 3 更容易观察多种操作。但 Proxy 本身不等于响应式系统,Vue 还负责依赖关联、触发更新与调度,直接操作原始对象也可能绕过代理。

  • 属性访问器与对象代理的拦截范围不同
  • 新增、删除与枚举可使用不同代理陷阱处理
  • 必须通过响应式入口访问,代理不是全局监听器

已有属性的访问器与整个对象的代理

给一个字段定义 getter/setter,可以在读取和赋值时插入逻辑,但没有为新字段预先安装访问器时,普通新增操作不会自动走已有字段的 setter。这也是讨论 Vue 2 对象动态属性时需要提到专用 API 的原因,不应把它误解成 JavaScript 本身不允许添加属性。

Proxy 的 set 可以观察经代理新增字段的赋值,deleteProperty 可以观察删除,ownKeys 可以参与枚举。这些能力便于框架区分读取某个字段和遍历整个对象等不同依赖。数组同样是对象,但 Vue 仍需针对数组、集合、深层对象和迭代语义处理细节,不能简化为换一个构造函数就实现了整个框架。

表格行动态增加字段时要走正确入口

假设表格行最初只有 name,收到后端补充信息后要增加 status。在 Vue 3 中通过 reactive 返回的代理更新这个字段,框架可以观察相关操作;若代码一直持有创建代理之前的原始对象并直接修改它,写操作可能绕过代理入口,不能期待同样的触发效果。

这种问题常见于把原始对象交给第三方库,又在另一处读取代理。应明确数据所有权,尽量在应用层通过响应式对象更新,或者在第三方回调中把变化同步回约定入口。为了调试暂时取得原始对象,不应演变成整个业务到处混用 raw 与 proxy。

观察通过代理与绕过代理的写入JavaScript
const raw = { count: 0 };
const proxy = new Proxy(raw, {
  set(target, key, value, receiver) {
    console.log('set', key);
    return Reflect.set(target, key, value, receiver);
  }
});
proxy.count = 1;
raw.count = 2;
console.log(proxy.count);
查看输出与解释
set count
2

这是可独立运行的 JavaScript 代理示意,不是 Vue 响应式实现。两次写入最终都影响同一个原始对象,但只有通过 proxy 的那一次触发 set 拦截,说明代理不会监控所有绕过它发生的操作。

拦截能力提升不代表没有使用边界

Proxy 只能包裹对象,不能直接代理字符串或数字这样的原始值,所以 Vue 仍需要 ref 等容器接口。对象解构得到一个普通原始值后,后续读取这个局部变量也不再是读取代理属性;这与 Proxy 能观察对象操作并不矛盾。

此外,代理与原始对象的引用身份不同,集合键、第三方实例和不可扩展对象等情况需要按框架 API 约定处理。性能也不能只依据“Proxy 更新”就断言一定更快,实际成本取决于访问模式、依赖规模和渲染工作。面试回答应把能力改善与应用层的正确使用同时说明。

回答前,多想一步

容易答错的地方

把 Proxy 等同于自动刷新页面
原生 Proxy 只提供拦截机制,不会自行建立 Vue 组件订阅或更新 DOM。框架需要在读取时记录依赖,并在写入后触发相应处理;代码示例里的 console.log 只是展示拦截发生。
认为 Vue 3 对所有对象都无条件深度代理
reactive 有适用目标与代理规则,特殊实例及选择 shallow、markRaw 等 API 时会有不同语义。不能用普通嵌套对象的经验推断所有浏览器对象或第三方类实例的行为。
试着用自己的话回答

面试官还会怎么问?

为什么修改原始对象后读取代理也可能看到新值?

代理通常仍以该原始对象为目标,因此后续主动读取可以看到修改后的数据。问题在于那次写入没有经过框架需要的拦截入口,已有订阅是否及时被触发与读取能否看到值是两个问题。

解构 reactive 对象后是不是所有数据都失去响应式?

要看解构得到的是什么。取出的原始值成为普通局部值,不再通过代理字段追踪;取出的嵌套对象可能仍是响应式代理。需要保持字段关联时可以使用 toRef、toRefs 或 getter。

Proxy 能解决对象替换造成的引用问题吗?

不能自动让所有持有旧引用的代码转向新对象。状态容器与引用关系仍需明确设计;如果需要频繁整体替换对象,可以根据需求选用 ref 等更合适的入口。

从一道题,走向一组知识

把知识连起来

响应式原理

Vue 的 computed 和模板里调用方法都能派生值,什么输入下 computed 的缓存才是决定性优势?

代理访问建立依赖后,继续理解 computed 如何利用这些依赖缓存派生计算。

响应式原理

Vue 3.5 的 <script setup> 中解构 props 为什么还能保持响应式,和普通 reactive 解构有何不同?

普通代理解构与 Vue 3.5 的编译器 props 解构机制不同,需要分别判断。

参考资料

  • Vue Reactivity Fundamentals
  • Vue Reactivity in Depth

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 已有属性的访问器与整个对象的代理
  3. 表格行动态增加字段时要走正确入口
  4. 拦截能力提升不代表没有使用边界
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑