可通过闭包或类封装实现函数调用统计与参数记录:闭包轻量且隔离性好,类适合复杂管理;二者均避免全局变量污染,支持状态持久化、复位及监控。
可以通过闭包或类封装来实现函数调用次数统计和参数历史记录,核心是把状态(计数器、参数列表)保存在函数外部但可被持续访问的作用域中。
定义一个工厂函数,返回带记忆能力的函数,内部变量不会被外部直接修改,保证数据隔离:
callCount 记录次数,history 存储每次的参数数组getStats() 和 getHistory() 方法供调试或监控示例:
function makeTracked(fn) {
let callCount = 0;
const history = [];
const tracked = function(...args) {
callCount++;
history.push([...args]); // 浅拷贝参数,避免后续修改影响记录
return fn.apply(this, args);
};
tracked.getStats = () => ({ count: callCount, history: [...history] });
tracked.reset = () => { callCount = 0; history.length = 0; };
return tracked;
}
// 使用
const add = makeTracked((a, b) => a + b);
add(1, 2); // → 3
add(3, 4); // → 7
console.log(add.getStats());
// { count: 2, history: [[1, 2], [3, 4]] }
当需要追踪多个函数、支持清除/导出/持久化,或配合 TypeScript 类型约束时,类更清晰可控:
CallRecord 实例,含 name、count、calls 等字段track(fn, name?) 方法生成代理函数示例简版:
class CallTracker {
constructor() {
this.records = new Map();
}
track(fn, name = fn.name || 'anonymous') {
if (!this.records.has(name)) {
this.records.set(name, { count: 0, calls: [] });
}
const record = this.records.get(name);
return (...args) => {
record.count++;
record.calls.push({ timestamp: Date.now(), args: [...args] });
return fn.apply(this, args);
};}
getSummary() {
const summary = {};
for (const [name, rec] of this.records) {
summary[name] = { count: rec.count, recent: rec.calls.slice(-3) };
}
return summary;
}
}
const tracker = new CallTracker();
const multiply = tracker.track((x, y) => x * y, 'multiply');
multiply(2, 3); multiply(4, 5);
console.log(tracker.getSummary());
// { multiply: { count: 2, recent: [ {...}, {...} ] } }
实际使用中需注意几个细节,避免踩坑:
[...args])只做浅拷贝。需深拷贝时可用 JSON.parse(JSON.stringify(args))(仅限可序列化值),或引入 structuredClone(现代浏览器)history.shift() 踢出旧记录async 函数,因为 return fn(...) 会正确传递 Promise@track,语法更简洁,适合类方法追踪直接在全局声明 let count = 0 再在函数里自增,看似简单,但会导致:

闭包或类的方式天然解决这些问题,代码更健壮、可维护性更强。