劫持console对象的核心思路是保存原始方法后覆写console方法,在新函数中注入时间戳再调用原始逻辑。因proxy无法可靠代理非扩展的宿主对象console,故采用bind绑定确保this正确、透传所有参数并提取iso时间字符串实现无侵入日志增强。

劫持 Console 对象的核心思路
JavaScript 中 console 是全局对象,其方法(如 log、warn、error)都是可重写的普通函数。通过代理(Proxy)或直接覆写,能在不修改业务代码的前提下拦截所有调用,并在原始逻辑前/后注入时间戳等元信息。
使用 Proxy 劫持 console 的限制与替代方案
Proxy 无法直接代理 console 对象本身——因为 console 是一个非扩展、不可配置的宿主对象(尤其在浏览器中),对它使用 new Proxy(console, {...}) 虽不报错,但多数方法调用不会触发 get 或 apply 拦截器(各浏览器兼容性差,Chrome/Firefox 表现不一致)。因此不推荐用 Proxy 直接代理 console。
更可靠的做法是:**保存原始方法 → 覆写 console 方法 → 在新函数中注入时间戳 → 调用原始方法**。
安全、通用的劫持实现(支持多参数 & 保留堆栈)
以下代码可在页面加载早期(如 script 标签内或 DOMContentLoaded 前)执行,确保覆盖所有后续日志:
// 保存原始 console 方法
const originalConsole = {
log: console.log.bind(console),
info: console.info.bind(console),
warn: console.warn.bind(console),
error: console.error.bind(console),
debug: console.debug.bind(console)
};
// 通用日志包装器
const withTimestamp = (method) => (...args) => {
const now = new Date().toISOString().slice(11, -1); // "HH:mm:ss.SSS"
method.apply(console, [`${now} ›`, ...args]);
};
// 覆写常用方法
console.log = withTimestamp(originalConsole.log);
console.info = withTimestamp(originalConsole.info);
console.warn = withTimestamp(originalConsole.warn);
console.error = withTimestamp(originalConsole.error);
console.debug = withTimestamp(originalConsole.debug);
说明:
- 用
bind(console)确保原始方法 this 正确,避免丢失上下文 -
toISOString().slice(11, -1)提取时分秒毫秒(如 "14:23:05.123"),简洁且无时区干扰 - 使用
...args完整透传所有参数,支持对象、格式化字符串(console.log('a=%d', 123))等原生行为 - 不影响
console.table、console.group等未覆写方法,可按需补充
进阶:仅开发环境启用 & 避免重复劫持
为防止多次加载脚本导致嵌套劫持(如时间戳叠加),建议加防护:
if (!console._timestamped) {
console._timestamped = true;
// 执行上述覆写逻辑...
}
结合环境判断(如 process.env.NODE_ENV === 'development' 或 location.hostname === 'localhost')可确保生产环境不受影响。











