可通过 Object.defineProperties 配合 get/set 陷阱为对象属性添加访问计数器,实现轻量级监控;需保留原始描述符元信息,用 WeakMap 存储计数防泄漏,并提供 enableMonitor 等工具方法支持按需启停与查询。

可以通过 Object.defineProperties 配合 get 和 set 陷阱,在不侵入业务逻辑的前提下,为对象属性添加访问计数器,实现轻量级的底层监控。
监控单个对象的属性访问频次
对目标对象的每个可监控属性,用 defineProperty(或 defineProperties)重定义其访问器,内部维护一个计数 Map:
- 在
get中递增对应属性的访问次数,并可触发日志、上报或阈值告警 - 在
set中同样计数(如需监控修改频次),同时确保值被正确赋值 - 保留原始属性描述符中的
enumerable、configurable等元信息,避免破坏对象行为
批量注入监控且兼容原有数据
使用 Object.defineProperties 可一次性为多个属性添加监控逻辑,比循环调用 defineProperty 更简洁高效:
- 先用
Object.getOwnPropertyDescriptors(obj)获取原始描述符 - 遍历 descriptors,对需要监控的属性,将
value或writable替换为get/set函数,并挂载计数逻辑 - 注意:若原属性是数据属性(含
value),需将其值暂存,供get返回;若已是访问器,则需合并逻辑
避免污染与支持动态扩展
监控逻辑应与业务解耦,推荐以下实践:
- 将计数器单独存于
WeakMap,键为被监控对象,值为Map,防止内存泄漏 - 提供
enableMonitor(obj, keys?)和getAccessCount(obj, key)等工具方法,便于按需开启/查询 - 若对象后续新增属性(如通过
obj.newField = ...),默认不监控;需显式调用再定义,或结合Proxy做兜底(defineProperties本身不响应动态新增)
实际示例:监控用户模型关键字段
比如监控 user.name 和 user.email 的读取频次:
- 创建
const counters = new WeakMap() - 调用
Object.defineProperties(user, { name: { get() { record('name'); return this._name; }, set(v) { record('name', 'set'); this._name = v; } }, email: { ... } }) -
record(key, type = 'get')内部查counters并累加,支持采样上报或控制台调试输出










