必须用 toraw()(vue 3)、tojs()(mobx)或手动剥离 __ob__(vue 2)才能真正脱敏;object.assign() 浅拷贝无法剥离响应式代理或可观测装饰,会导致意外更新。

直接用 Object.assign() 对 Vue 或 MobX 的响应式对象做浅拷贝,**无法真正“脱敏”**——拷贝结果仍可能携带响应式代理(如 Vue 3 的 Proxy)或可观测装饰(如 MobX 的 ObservableObject),导致后续操作意外触发响应更新或监听。所谓“脱敏”,核心是**剥离响应式系统附加的元信息,只保留原始数据结构和值**。
Vue 2:先解包再拷贝(避开 Observer 实例)
Vue 2 中响应式对象被包裹在 Observer 实例中,其 __ob__ 属性是关键标识。直接 Object.assign({}, reactiveObj) 会把 __ob__ 当作普通属性拷进去,新对象仍被 Vue 监控。
- 推荐做法:用
JSON.parse(JSON.stringify())(仅限可序列化字段)或更稳妥的Object.assign({}, JSON.parse(JSON.stringify(obj))) - 更优解:利用 Vue 提供的
toRaw()(Vue 3)不适用;Vue 2 可手动剥离:const raw = Object.assign({}, obj); delete raw.__ob__;
但需注意:若对象嵌套含响应式子对象,此法仅处理顶层,需递归清理或改用lodash.clonePlainObject()
Vue 3:必须用 toRaw() 配合 Object.assign()
Vue 3 响应式基于 Proxy,无法通过删属性解除,toRaw() 是官方唯一安全解包 API。
- 正确写法:
import { toRaw } from 'vue';<br>const plainCopy = Object.assign({}, toRaw(reactiveObj)); - ⚠️ 注意:
toRaw()返回的是原始对象引用,若原对象后续变更,plainCopy不会自动同步——这正是“脱敏”所需行为 - 若需深层脱敏(如嵌套 reactive),
toRaw()递归有效,无需额外处理
MobX:用 mobx.toJS() 替代 Object.assign()
MobX 的 observable 对象不是普通对象,Object.assign() 拷贝后仍保留 Symbol(mobx administration) 等隐藏字段,新对象仍受 MobX 管理。
- 标准方案:
import { toJS } from 'mobx';<br>const plainCopy = toJS(observableObj); // 深拷贝、完全脱敏 - 若坚持用
Object.assign()浅拷贝:先用mobx.toJS()转为纯 JS 对象,再拷贝(冗余,无必要) - 避免:
Object.assign({}, observableObj)—— 拷贝结果仍是 observable,且可能丢失计算属性(computed)的当前值
通用建议:明确“浅拷贝”是否真够用
多数场景下所谓“脱敏提取”,真实需求是获取一份**不受响应式系统干扰的独立数据副本**。此时:
- 若只需顶层字段:Vue 3 用
toRaw() + Object.assign();MobX 用toJS() - 若含嵌套对象/数组:
toRaw()和toJS()均默认深度处理,比手写递归Object.assign()更可靠 - 不要试图用
Object.assign()“绕过”响应式系统——它不是设计来处理代理对象的工具
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











