你给一个普通对象设置 user.age = -5,什么都不会发生。没有报错,没有警告——对象默默接受了一个毫无意义的值,而bug会在三个文件之外、在某个信任 age 是合法数字的代码里突然爆发。
那些看起来"自动感知"状态变化的框架——Vue的响应式系统、在边界拒绝非法输入的校验库、一碰就懒加载关联数据的ORM——都在用同一个原生JavaScript特性解决这个问题。这个特性就是 Proxy,但大多数教程只用一段话就把它带过了。
![]()
Proxy到底是什么?它是对象的"替身",拦截对对象的操作,不是拷贝,也不是包装类。通过 get、set、has、deleteProperty、ownKeys 这些陷阱(trap),你可以校验、隐藏、记录属性访问。而 Reflect 是让陷阱写对的工具箱——它存在的意义,就是为了防止一个特定的bug。
为什么不用getter/setter?手写校验每个字段的getter/setter对,能解决单个字段的问题。但加上 email、score、role,你就得维护四套几乎相同的代码,每一套都是忘记检查的地方。漏掉一个,那个字段就静默接受垃圾数据。校验逻辑也散落在各个字段里,没法集中审计。
你真正想要的是:"只要这个对象的任何属性被读取或写入,就运行这段代码"——一个拦截点,而不是N个手写对。这正是Proxy给你的能力。
核心心智模型:把Proxy想象成每个操作前面的检查站。任何对目标对象的属性访问,都会先经过这个检查站,由你决定放行、修改还是拒绝。这就是Vue 3响应式系统底层的机制。
实际能做什么?用Proxy可以构建一个微型响应式状态系统——这正是Vue 3内部使用的机制。但也要注意它的不变量(invariants)、坑和性能权衡,这些在生产环境里会坑到人。
谁该看这篇?日常写JavaScript或TypeScript、已经熟练使用对象和类、听说过Proxy但没用过的人。或者你在别人代码里看到 Reflect.get(target, prop, receiver),疑惑为什么不直接写 target[prop]——这篇就是为你准备的。
关键要点:Proxy是拦截点而非拷贝;Reflect让陷阱写对;校验逻辑集中在一处而非散落各字段;响应式系统是Proxy的典型应用。从第一个 get/set 陷阱开始,到构建微型响应式系统,再到边界情况和最佳实践,这篇指南会带你完整走一遍。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.