Proxy 可拦截对象的 get/set 操作实现访问日志与频次统计:记录属性读写时间、调用栈、新旧值;用 Map 统计次数;过滤内部属性;封装为可复用函数并注意 Reflect 转发和 Symbol 支持。

可以用 Proxy 拦截对象的读取(get)和写入(set)操作,在每次访问或修改属性时自动记录日志、统计频次或收集元数据。
创建带访问日志的代理对象
通过 Proxy 的 get 和 set 拦截器,把每次属性读写行为打印到控制台或存入日志数组:
- 在
get中记录谁访问了哪个属性、何时访问、返回值是什么 - 在
set中记录谁修改了哪个属性、旧值/新值、是否成功赋值 - 可选地添加时间戳、调用栈(
new Error().stack)辅助定位问题
统计属性访问频次
用一个 Map 或普通对象维护每个属性的访问次数,每次 get 或 set 时自增计数:
- 初始化一个空对象如
const accessCount = {} -
get(target, prop)中执行accessCount[prop] = (accessCount[prop] || 0) + 1 - 支持按需导出统计结果,例如
Object.entries(accessCount)排序查看最热属性
区分内部访问与业务访问
避免日志被框架或工具(如 Vue 响应式、console.log 展开)干扰,可加简单过滤逻辑:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
立即学习“Java免费学习笔记(深入)”;
- 跳过以
_、$开头的属性(常见于内部字段) - 跳过
toString、valueOf等内置方法调用 - 用
Reflect.get(target, prop, receiver)保证原语义,不破坏原型链或 this 绑定
封装成可复用的监控函数
把日志和统计逻辑抽成工厂函数,便于在不同对象上复用:
- 接收原始对象和配置项(如是否启用日志、是否统计、忽略列表)
- 返回代理对象,并暴露
getStats()、clearLogs()等方法 - 示例调用:
const loggedUser = createLoggedProxy(user, { log: true, count: true })
不复杂但容易忽略细节,比如忘记用 Reflect 转发操作会导致功能异常,或者没处理 Symbol 属性导致漏监控。实际使用时建议配合 WeakMap 存储私有状态,避免内存泄漏。

















