proxy 通过 get 陷阱实现读取时动态格式化:访问属性时按规则实时转换(如日期转字符串、数字加千分位),不修改原始数据;需避免无限递归,枚举和序列化等操作不受影响。

Proxy 可以拦截对象的读取操作,在 get 陷阱中动态生成格式化后的值,而不是预先计算或修改原始数据。
用 Proxy 拦截 get 实现即时格式化
核心思路是:当访问某个属性时,不直接返回原始值,而是根据属性名或值类型,实时返回格式化结果(如日期转字符串、数字加千分位、布尔转中文等)。
- 创建 Proxy 时传入目标对象和 handler 对象
- 在 handler 的
get(target, prop)中判断需要格式化的字段 - 对匹配的字段做转换,其余属性仍按原样返回
- 注意避免无限递归:格式化时应读取
target[prop],而非target[prop]触发再次代理
常见格式化场景示例
比如处理用户信息对象,让 birthday 自动转为「YYYY-MM-DD」,salary 加千分位和单位,isActive 显示为「是/否」:
const user = { name: '张三', birthday: new Date('1990-05-12'), salary: 123456.78, isActive: true };
const formattedUser = new Proxy(user, {
get(target, prop) {
if (prop === 'birthday') {
return target[prop]?.toISOString().split('T')[0] || '';
}
if (prop === 'salary') {
return target[prop] != null ? `¥${target[prop].toLocaleString()}` : '';
}
if (prop === 'isActive') {
return target[prop] ? '是' : '否';
}
return target[prop]; // 其他属性保持原样
}
});
console.log(formattedUser.birthday); // "1990-05-12"
console.log(formattedUser.salary); // "¥123,456.78"
console.log(formattedUser.name); // "张三"
支持嵌套对象与可配置规则
若需更灵活控制,可把格式化逻辑抽成映射表,支持嵌套路径(如 profile.phone)或函数式规则:
- 定义
formatters对象,键为属性路径,值为格式化函数 - 在
get中解析prop,查表执行对应函数 - 对嵌套对象,可递归代理其子属性(但注意循环引用和性能)
- 推荐只代理顶层对象,深层格式化由业务层按需调用,避免过度代理
注意事项与边界情况
Proxy 格式化是“读时计算”,不影响原始数据,但要注意:
-
in操作符、Object.keys()等枚举操作不会触发get,所以它们看到的仍是原始属性名和值 - 如果需要格式化后也参与枚举,得配合
ownKeys和getOwnPropertyDescriptor一起使用 - JSON.stringify() 默认忽略 Proxy 行为,会序列化原始值;如需格式化后导出,应手动调用或重写
toJSON - 不要在
get中修改target,否则破坏响应式语义,且可能引发不可预期副作用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











