Proxy 我踩过的那些坑
刚学 Proxy 时,我以为它就是“把对象包装一下,搞个监控”,结果被老板当众指出页面卡死。痛定思痛,我总结了这篇小抄,照着做基本不会再掉坑。
常见痛苦场景
- 直接改对象属性,毫无日志、校验和异常提示,一出 bug 全靠猜
- 给属性加逻辑,只能在每处调用前手写 if 判断,代码臃肿得像圣诞树
- 一旦验证规则改一改,页面突然卡成 PPT,原因是没发现 Proxy 里的同步日志写得太多
我以前踩的坑 vs 现在的做法
曾经的我 | 现在的我 |
---|---|
在业务代码里到处塞 console.log | 把日志、校验全部收进一个 Proxy handler |
直接写 obj[prop] 去设置值 | 用 Reflect.set,既安全又符合规范 |
把重计算放在 get/set 里 | 用节流或将复杂运算挪出 Proxy,只在关键路径打日志 |
动手三步搞定
-
造原始数据
const person = {name: 'John Doe',age: 42,nationality: 'American' };
-
写 handler:先日志后验证,别搞反
日志在前,一眼能看见哪里出错;验证在后,卡住脏数据。
const handler = {get(obj, prop) {if (!(prop in obj)) {console.log(`警告:对象上没有 ${prop}`);return undefined;}console.log(`读取 ${prop},当前值:${Reflect.get(obj, prop)}`);return Reflect.get(obj, prop); // 必须 return 出去,否则读出来是 undefined},set(obj, prop, value) {if (prop === 'age' && typeof value !== 'number') {console.log('age 必须是数字');return false; // 返回 false 表示设置失败}if (prop === 'name' && value.trim().length < 2) {console.log('name 长度必须 ≥ 2');return false;}console.log(`修改 ${prop}:${obj[prop]} → ${value}`);return Reflect.set(obj, prop, value);} };
-
套壳使用:把逻辑锁进 proxy,业务只关心 proxy
const personProxy = new Proxy(person, handler);// 体验效果 personProxy.name; // 日志:读取 name... personProxy.age = 43; // 日志:修改 age... personProxy.age = 'old'; // 警告:age 必须是数字
一点额外叮咛
- Reflect 不是摆设,它和 Proxy 的方法签名完全对齐,用它比手写
obj[prop]
少踩奇奇怪怪的 this 坑 - 千万别在 handler 里做重计算、网络请求,页面秒卡不是梦
- 生产环境里可以把 console 换成轻量埋点,别让调试语句拖慢速度