捕获JavaScript控制台日志?

83
2个回答

167

可以使用以下方法劫持 JavaScript 函数:

(function(){
    var oldLog = console.log;
    console.log = function (message) {
        // DO MESSAGE HERE.
        oldLog.apply(console, arguments);
    };
})();
  1. 第一行使用闭包将您的函数封装起来,这样其他函数就无法直接访问oldLog(出于可维护性的考虑)。
  2. 第二行捕获原始方法。
  3. 第三行创建一个新函数。
  4. 第四行发送message到服务器。
  5. 第五行调用原始方法,就像它最初被处理的那样。

使用apply是为了我们可以使用原始参数在console上调用它。简单地调用oldLog(message)会失败,因为log依赖于它与console的关联。


更新根据zzzzBov的评论,在IE9中,console.log实际上不是函数,所以oldLog.apply会失败。有关更多详细信息,请参见console.log.apply not working in IE9


1
你的代码在IE中会出现问题,因为console.log在IE中实际上不是一个Function实例。 - zzzzBov
@zzzzBov 很有趣。我认为分配 console._oldLog = console.log; console._oldLog(message); 应该可以工作,但如果 console 本身是一个托管对象,则不能保证更改会生效。不幸的是,我没有 IE 来测试这个了。 - Brian Nickel
是的,你仍然可以这样调用_oldLogoldLog = Function.prototype.bind.call(console.log, console)适用于IE9+,但需要为IE8及以下版本提供Function.prototype.bind的polyfill。 - zzzzBov
13
这种方法的问题在于我们无法捕获日志行,它总是发送相同的行。有没有可能解决这个问题?谢谢。 - Guilherme Nascimento
@GuilhermeNascimento 提出了一个很好的问题。你如何保留原始的日志行? - rex
显示剩余2条评论

27

简单:

function yourCustomLog(msg) {
  //send msg via AJAX
}

window.console.log = yourCustomLog;

你可能想要覆盖整个console对象以捕获console.infoconsole.warn等:

window.console = {
  log : function(msg) {...},
  info : function(msg) {...},
  warn : function(msg) {...},
  //...
}

2
你不能使用 window.console = { ... },因为 window.console 是只读属性! - Luillyfe
4
@Luillyfe似乎实际上起作用了,那么你的评论实际上是在暗示什么? - humanityANDpeace
我写了一个小的npm包来完成同样的事情。这里有一个详细的答案-https://stackoverflow.com/a/75377394/11565176 - nsrCodes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接