proxy 实现属性访问统计分析的核心是通过 get 拦截器捕获读取行为,记录频次、路径与调用栈等信息,实现无感监控;重点采集属性名及次数、调用堆栈、时间戳与上下文、首次访问标记,并推荐代理子对象而非整个 window 以规避兼容与性能风险。

Proxy 实现属性访问统计分析,核心在于用 get 拦截器捕获每次读取行为,并记录频次、路径、调用栈等关键信息。它不修改原有逻辑,也不依赖侵入式埋点,属于运行时无感监控。
统计哪些访问行为
真正有用的统计不是“谁读了什么”,而是“为什么读、在哪读、读得是否合理”。重点采集:
-
属性名 + 访问次数:识别高频访问字段(如
window.location、document.cookie) -
调用堆栈(stack):定位具体哪一行代码触发访问,便于归因(可用
new Error().stack截取) - 访问时间戳与上下文:区分初始化阶段、用户交互后、定时任务中等场景
- 是否首次访问:配合 Set 或 Map 标记,识别冷启动时的环境探测行为
基础统计代理写法
以监控 window 对象为例,避免直接代理整个 window(存在兼容与性能风险),推荐代理其子对象或关键属性:
const accessLog = new Map(); // key: 'location.href', value: { count: 1, firstAt: Date.now(), stacks: [] }
const windowProxy = new Proxy(window, {
get(target, prop) {
const key = String(prop);
const now = Date.now();
if (!accessLog.has(key)) {
accessLog.set(key, {
count: 1,
firstAt: now,
lastAt: now,
stacks: [new Error().stack.split('\n')[2]?.trim() || 'unknown']
});
} else {
const entry = accessLog.get(key);
entry.count++;
entry.lastAt = now;
// 可选:只存前3次堆栈,防内存膨胀
if (entry.stacks.length
<p>注意:必须用 <code>windowProxy</code> 替代原 <code>window</code> 使用,否则拦截无效;实际项目中建议只代理明确需要监控的子对象(如 <code>new Proxy(navigator, {...})</code>)。</p>
<h3>进阶:支持过滤与聚合分析</h3>
<p>真实场景需排除干扰(如框架内部读取、轮询等)。可在 handler 中加入判断逻辑:</p>
- 用正则忽略特定属性:
if (/^__|on\w+|toString$/.test(prop)) return Reflect.get(...) - 按时间窗口聚合:每5秒汇总一次
accessLog,输出 Top5 属性及平均响应延迟(需配合performance.now()) - 导出为结构化数据:
Array.from(accessLog.entries()).map(([k, v]) => ({ prop: k, ...v })),方便送入分析平台或生成可视化报表
注意事项与边界
Proxy 统计虽强大,但有现实约束:
-
不能拦截隐式访问:比如
with语句、eval内部变量、原型链上未定义但被继承的属性(需配合has+getPrototypeOf补充) - 性能开销真实存在:高频访问对象(如 Canvas 上下文、大量 DOM 节点)不宜全量代理,应按需启用
-
部分浏览器 API 不可代理:如
window本身在某些上下文(iframe、Service Worker)中受限,可退而代理self或目标子对象
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











