【问题标题】:Override console.log in JavaScript在 JavaScript 中覆盖 console.log
【发布时间】:2016-06-03 13:14:37
【问题描述】:

我想重写console.log 方法以在调用console.log 时调用一组任务。我参考了其他 Stackoverflow 答案,但这给了我错误:

未捕获的 RangeError:超出最大调用堆栈大小。

这就是我想做的:

backupconsolelog = console.log;

console.log = function(arguments)
{
    //do my tasks;

    backupconsolelog(arguments);
}

更新 1:不知何故成功地覆盖了 console.log,但我现在无法在完成覆盖的同一个 .js 文件中执行 console.log(displaySomethingInConsole)。这以某种方式导致对console.log 的递归调用,并再次给出Uncaught RangeError: Maximum call stack size exceeded.

如何在同一个 .js 文件中使用 console.log()?

更新 2:我有一个 check() 函数,它被覆盖的 console.log 调用。但是,check() 函数内部有一个console.log 调用导致Maximum call stack size exceeded. 错误。

更新 3:又出错了! :(

未捕获的类型错误:非法调用

var _log = window.console.log;
window.console.log = function () {
_log.apply(this, arguments);
check();
};

_log("aaa");
check() {};

更新 4Bindingconsole_log,即console.log.bind(console) 清除它。

【问题讨论】:

标签: javascript overriding console.log


【解决方案1】:

如果您收到 Maximum call stack size exceeded 错误,这几乎肯定意味着您的函数是 recursively calling itself infinitely。您找到的解决方案以及 RaraituL 显示的解决方案应该可以完美运行。您可能不止一次调用了设置呼叫重定向的代码部分。

// First time:
backupconsolelog = console.log.bind(console);
console.log = function() {
    backupconsolelog.apply(this, arguments);
    /* Do other stuff */
}
// console.log is now redirected correctly

// Second time:
backupconsolelog = console.log;
// Congratulations, you now have infinite recursion

您可以添加一些调试信息(显然,不要使用console.log,而是尝试使用debugger; 来创建自动断点)您可以在其中设置重定向以查看代码的位置和时间调用。

更新

这可能属于评论:您的console.log 重定向函数显然调用了一些名为check 的函数。这个check 函数然后调用console.log,如果你的 函数 - 不是原来的。让check 函数调用原始 实现。

backupconsolelog = console.log.bind(console);

console.log = function() {
    check();
    backupconsolelog.apply(this, arguments);
}

function check() {
    // This will call your function above, so don't do it!
    console.log('Foo');

    // Instead call the browser's original implementation:
    backupconsolelog('Foo');
}

更新 2

浏览器的console.log 实现的内部工作可能取决于或可能不取决于为this 引用设置的console。因此,您应该将console.log bound 存储到console,就像在我的代码中一样。

【讨论】:

  • 知道了!我在同一个 .js 文件中使用了其他一些 console.log() 消息,在该文件中我覆盖了 console.log() 方法,从而导致递归调用。但是,如果我需要在控制台中从同一个 .js 文件中显示某些内容(覆盖已完成),我该怎么做?
  • 不,据我所知,这不应该导致递归调用。尝试编辑您的问题以包含更多给您带来问题的代码。只要您只调用一次,RaraituL 的解决方案(和我的) 确实 工作。将那一小段代码移到另一个<script> 标签,这样就不会再让你头疼了。
  • check() 是我自己的函数,它是从 console.log 覆盖的函数中调用的。但是,在 check() 中,我再次使用了 console.log()。是这个问题吗?
  • 是的!这么多是的! console.log 现在是你的函数,它调用check(),它调用console.log,它是你的函数,它调用check(),以此类推。 . 让check 改为调用backupconsolelog()
  • 那行得通。 :) This 帮助理解。谢谢。
【解决方案2】:
// keep reference to original function
var _log = window.console.log;

// overwrite function
window.console.log = function () {
    _log.apply(this, arguments);
    alert(arguments);
};

console.log("hello world");

【讨论】:

  • 我仍然收到“未捕获的 RangeError:超出最大调用堆栈大小。”错误。 ://
  • RaraituL 的解决方案有效!您可能不止一次设置呼叫重定向。也请阅读我的答案。
  • 是的,我这样做了,但错误发生在我使用 console.log(displaySomeDataInConsole);在 .js 文件中。
  • 我应该使用 _log(displaySomeDataInConsole);在 .js 文件中?
  • 知道了!我在同一个 .js 文件中使用了其他一些 console.log() 消息,在该文件中我覆盖了 console.log() 方法,从而导致递归调用。但是,如果我需要在控制台中从同一个 .js 文件中显示某些内容(覆盖已完成),我该怎么做?
【解决方案3】:

在一些问题之后,我设法用winston + express替换了console.log。

我使用winston-sugar,因为它使配置更容易,但任何东西都可以工作。 (当您执行 npm install winston-sugar 时会创建 .config/winston.json) 想要用其他东西替换 console.log 的人可以看看最后 5 行,因为它提供了非常干净的代码。

我认为这是一种非常巧妙的方式,可以将快速登录到文件以及 console.log 中

const morgan = require('morgan');
const winstonLoader = require('winston-sugar');
winstonLoader.config('./config/winston.json');
const log = winstonLoader.getLogger('app');
log.stream = {
  write: function (message, encoding) {
    log.info(message);
  },
};

// Add some lines indicating that the program started to track restarts.
log.info('----------------------------------');
log.info('--');
log.info('-- Starting program');
log.info('--');
log.info('----------------------------------');

console.log = (...args) => log.info(...args);
console.info = (...args) => log.info(...args);
console.warn = (...args) => log.warn(...args);
console.error = (...args) => log.error(...args);
console.debug = (...args) => log.debug(...args);

如果您正在运行 express,则稍后在代码中。

// app.use(morgan('combined')); //replaced with the next line to get morgan logs into the winston logfiles.
app.use(morgan('combined', { stream: log.stream }));

【讨论】:

    【解决方案4】:

    您可能需要将原始方法绑定到控制台:

    var old = console.log.bind(console)
    console.log = (...args) => {
      // perform task
      alert('test')
      old.apply(null, args)
    }
    

    【讨论】:

    • 这是什么意思:"console.log = (...args) => "
    • () => {} 是一个箭头函数。 more ...args 是扩展运算符,允许使用将所有参数作为数组获取。 more 与函数 () {var args = [].slice.call(arguments)} 类似。对于像 console.log() 这样的可变参数函数很有用。
    • 这是JS吗?使用这个会导致Multiple markers at this line - Syntax error on token ">", invalid FunctionExpressionHeader - Syntax error on tokens, CallExpression expected instead
    • 是的,它是 ES6 又名 ES2015。你用的是什么环境?无论如何,如果 its a production code thats 应该在浏览器上下文中运行并且您想使用 es6 语法,您可能应该使用转译器,例如。 Babel。大多数 ES6 语法适用于较新的 nodejs 版本。否则你可以坚持使用 ES5。
    • 是的,我使用 Eclipse,代码应该在浏览器(客户端)中运行。尚未了解 Babel 和 ES2015,感谢您提供的信息。 :)
    【解决方案5】:

    这对我有用。

    let originalConsole = Object.assign({}, console);
    console.log = (value) => {
        //some cool condition
        if (true) {
            value = "new_log : " + value
        }
        originalConsole.log(value);
    };
    

    【讨论】:

    • 请不要对多个问题发布完全相同的答案。如果您觉得所有问题都在问同样的问题,请标记以将它们关闭为彼此重复。
    • @Bergi 好的,我明白了。现在我已经删除了喜欢这篇文章的另一个答案
    【解决方案6】:

    接受的答案将与提供的结构一起使用,除非您需要在运行的实例上多次“设置”覆盖。如果您有一个实时容器或 lambda 函数,您将面临参数数组自身建立的风险。

    [ arg1 ] -> [ [arg1] , arg2 ] -> [ [ [ arg1 ] , arg2] , arg3 ] 
    

    例如:

    function x(){
      var log = console.log;
      console.log = function () {
            var args = Array.from(arguments);
            args.push('post fix');
            log.apply(console, args);
        }
    }
    
    new x()
    console.log(1)
    new x()
    console.log(2)
    
    OUTPUTS:
    1 post fix
    2 post fix post fix
    
    

    解决方案:

    确保您是否需要将此功能用作中间件,例如, 您在中间件函数之外维护引用,例如:

    var log = console.log;
    function x(){
      console.log = function () {
            var args = Array.from(arguments);
            args.push('post fix');
            log.apply(console, args);
        }
    }
    
    new x()
    console.log(1)
    new x()
    console.log(2)
    
    OUTPUTS: 
    1 post fix
    2 post fix
    

    或者更好……

    const log = console.log;
    function middleWare() {
        console.log = (...args) => {
            log(...args, 'post fix');
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-28
      • 1970-01-01
      • 2013-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-25
      相关资源
      最近更新 更多