我可以在 javascript 中扩展控制台对象(用于重新路由日志记录)吗?

Posted

技术标签:

【中文标题】我可以在 javascript 中扩展控制台对象(用于重新路由日志记录)吗?【英文标题】:Can I extend the console object (for rerouting the logging) in javascript? 【发布时间】:2012-03-05 20:58:06 【问题描述】:

是否可以扩展控制台对象?

我尝试了类似的方法:

Console.prototype.log = function(msg)
    Console.prototype.log.call(msg);
    alert(msg);

但这没有用。 我想通过 log4javascript 之类的框架向控制台对象添加额外的日志记录,并且在我的代码中仍然使用标准控制台对象(如果 log4javascript 不可用)。

提前致谢!

【问题讨论】:

为什么要扩展原型对象而不是扩展Console 对象本身?你有没有打电话给new Console() 【参考方案1】:

尝试以下操作:

(function() 
    var exLog = console.log;
    console.log = function(msg) 
        exLog.apply(this, arguments);
        alert(msg);
    
)()

【讨论】:

【参考方案2】:

您也可以通过这种方式添加日志时间:

添加 Momentjs 或使用 New Date() 代替 moment。

var oldConsole = console.log;
console.log = function()
    var timestamp = "[" + moment().format("YYYY-MM-DD HH:mm:ss:SSS") + "] ";
    Array.prototype.unshift.call(arguments, timestamp);
    oldConsole.apply(this, arguments);
;

【讨论】:

这不起作用,因为它会生成“未定义时刻”错误。 你必须使用 npm install moment 来安装 moment 好吧,我想,不过我更喜欢原生解决方案。例如,NPM 是需要存在的“另一个”东西【参考方案3】:

这确实与其他人给出的解决方案相同,但我相信这是完成此任务的最优雅和最不笨拙的方法。扩展语法 (...args) 使 sure not a single argument is lost。

var _console=...console

console.log = function(...args) 
    var msg = ...args[0];
    //YOUR_CODE
    _console.log(...args);

【讨论】:

很好地使用了 spread/rest 语法,但它不是必需的,有一个小 1 行的方式支持 IE 并且不会覆盖上面的 protos。【参考方案4】:
// console aliases and verbose logger - console doesnt prototype
var c = console;
c.l = c.log,
c.e = c.error,
c.v = c.verbose = function() 
    if (!myclass || !myclass.verbose) // verbose switch
        return;
    var args = Array.prototype.slice.call(arguments); // toArray
    args.unshift('Verbose:');
    c.l.apply(this, args); // log
;

// you can then do
var myclass = new myClass();
myclass.prototype.verbose = false;
// generally these calls would be inside your class
c.v('1 This will NOT log as verbose == false');
c.l('2 This will log');
myclass.verbose = true;
c.v('3 This will log');

我注意到上面 nitesh 对 Array.prototype.unshift.call 的使用是添加“详细:”标签的更好方法。

【讨论】:

【参考方案5】:

适用于 ECMAScript 2015 及更高版本

您可以使用ECMAScript 2015 标准中较新的Proxy 功能来“劫持”全局console.log。

源代码

'use strict';

class Mocker 
  static mockConsoleLog() 
    Mocker.oldGlobalConsole = window.console;

    window.console = new Proxy(window.console, 
      get(target, property) 
        if (property === 'log') 
          return function(...parameters) 
            Mocker.consoleLogReturnValue = parameters.join(' ');
          
        

        return target[property];
      
    );
  

  static unmockConsoleLog() 
    window.console = Mocker.oldGlobalConsole;
  


Mocker.mockConsoleLog();

console.log('hello'); // nothing happens here

Mocker.unmockConsoleLog();

if (Mocker.consoleLogReturnValue === 'hello') 
  console.log('Hello world!'); // Hello world!
  alert(Mocker.consoleLogReturnValue);
  // anything you want to do with the console log return value here...

在线演示

Repl.it.

Node.js 用户...

...我不会忘记你。您可以获取此源代码并将window.console 替换为gloabl.console 以正确引用控制台对象(当然,摆脱alert 调用)。事实上,我最初编写了这段代码并在 Node.js 上进行了测试。

【讨论】:

与上面使用 6 行覆盖的答案相比,这是巨大的,我认为这对于简单的函数重写来说太过分了 不,不要使用代理劫持单个财产。【参考方案6】:

您可以使用以下方法覆盖console.log 函数的默认行为,下面的示例演示使用覆盖的函数记录行号。

let line = 0;
const log = console.log;
console.log = (...data) => log(`$++line ===>`, ...data)

console.log(11, 1, 2)
console.log(11, 1, 'some')

【讨论】:

以上是关于我可以在 javascript 中扩展控制台对象(用于重新路由日志记录)吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Chrome 的 JavaScript 中覆盖/扩展 ReferenceError?

扩展音频/HTMLMediaElement javascript 对象

在 Javascript 中扩展对象

在 Javascript 中扩展(继承)类(或对象)

在 javascript 中扩展 Array 对象的方法

我可以在 JavaScript 窗口全局对象中定义的某个对象中找到 JQuery 函数吗?