浅拷贝配合 proxy 可构建轻量级状态监听引擎:object.assign 创建初始副本,proxy 拦截读写实现按需响应、自愈机制与嵌套懒代理,weakmap 缓存子代理,通知解耦至外部处理。

浅拷贝配合 Proxy 能快速构建轻量级状态监听引擎,关键不在“复制得多深”,而在“代理得够准”——用 Object.assign({}, obj) 生成干净初始副本,再用 Proxy 拦截读写行为,既避免引用污染,又保留响应式控制权。
为什么选浅拷贝而非深拷贝
浅拷贝只复制第一层属性,速度快、内存开销小,适合配置对象、表单数据、UI 状态等结构扁平的场景。它不递归处理嵌套对象,正好把“是否需要深层监听”的决定权留给 Proxy 的 get 拦截器——需要时再惰性代理,不需要就保持原样,真正实现按需响应。
- 避免深拷贝带来的性能损耗和循环引用风险(如 Date、RegExp、Map 等无法序列化的值)
- 原始嵌套对象若无需监听(如常量配置、第三方库返回对象),可原样透出,不强制包裹
- 与 Proxy 的“懒代理”策略天然契合:只在属性被访问时判断是否要递归代理
用 Object.assign + Proxy 构建自愈型状态对象
浅拷贝提供初始快照,Proxy 提供行为控制。所谓“自愈”,是指当访问缺失属性、写入非法值或误改只读字段时,能自动回退或静默处理,而不是抛错或失控。
安装并运行 Aperture(Lightning Labs 的 L402 闪电反向代理),用于创建 L402 付费墙、配置付费 API 端点、为其他代理托管付费内容或测试 L402 认证流程。
- 用
Object.assign({}, original)创建初始副本,作为 Proxy 的 target,确保原始对象不受影响 - 在
get中:若 key 不存在于 target,尝试从 initial 副本取值(回退默认);若仍无,则返回undefined - 在
set中:对只读字段(如debug)直接返回true静默拒绝;对类型不符的赋值(如给 number 字段赋 string)跳过更新 - 暴露
.reset()方法:内部调用Object.assign(target, initial)一键还原
如何支持嵌套访问但不爆炸内存
浅拷贝后的对象,其嵌套子对象仍是原始引用。若需监听 state.user.name,必须在 get 返回前对子对象做代理——但绝不能每次都新建 Proxy。
- 用
WeakMap缓存已代理的子对象:if (proxyCache.has(value)) return proxyCache.get(value) - 仅当
value && typeof value === 'object' && !value.constructor.name.match(/^(Date|RegExp|Map|Set)$/)时才递归调用createReactive(value) - 对数组不做额外代理:它的
push/pop会触发set('0', x)和set('length', n),天然可捕获
通知机制要解耦,不要在 Proxy 里写 DOM 操作
Proxy 的职责是拦截和转发,不是渲染。每次 set 后应触发统一通知函数(如 trigger(key, oldValue, newValue)),由外部 effect 或订阅者决定是否更新视图、是否批量合并、是否延迟到下一帧。
- 禁止在 handler 里直接操作
document或调用setState - 推荐用
setTimeout(() => updateView(), 0)或queueMicrotask(updateView)避免同步卡顿 - 对高频变更(如输入框),可收集 key 列表,一次批量刷新,而非每次 set 都触发










