JavaScript - 覆盖 console.log 并保留旧函数

9
我想重写console.log并在我的新函数中调用它。
我尝试了以下代码,但是出现了“Uncaught TypeError: Illegal invocation”错误:
console.log = function() {
  this.apply(window, arguments);
}.bind(console.log);

console.log('as');

这是我的目标: console.error(exception); 应该做什么:
console.error = function() {
  if (typeof exception.stack !== 'undefined') {
    console.error(exception.stack);
  } else {
    console.error.apply(windows, arguments);
  }
}.bind(console.error);

console.error('as');
console.error({stack: 'my stack....'});

编辑: 实际上,在火狐浏览器中可以使用,但在Chrome浏览器中无法使用...

这是Chrome浏览器的一个bug:https://code.google.com/p/chromium/issues/detail?id=167911

很难确定您的目标是什么。您是否想在调用 console.log 的同时调用不同的函数,以及调用原始的 console.log - DCoder
我编辑了以添加我的目标。 - Charles
8个回答

9

达成您想要的最好方法:

// define a new console
var console=(function(oldCons){
    return {
        log: function(text){
            oldCons.log(text);
            // Your code
        },
        info: function (text) {
            oldCons.info(text);
            // Your code
        },
        warn: function (text) {
            oldCons.warn(text);
            // Your code
        },
        error: function (text) {
            oldCons.error(text);
            // Your code
        }
    };
}(window.console));

//Then redefine the old console
window.console = console;

点赞! 刚试了一下类似以下的代码: var msg=(function(oldCons){ return { log: function(text){ oldCons.log('%c' + text,"color:#00DFB9;background-color: #032320; font-size:2em; font-weight: bold; padding: 4px 6px;"); } }; }(window.console)); msg.log('Hello World !'); console.log('Hello World !'); - mike652638
你应该将你的代码作为答案发布,这可能会帮助一些人。它不适合作为评论格式。 - Ludovic Feltz
好的,感谢您的友情提醒。我上面的评论主要是为了感谢您所激发的灵感,让我意识到可以使用自定义样式来实现一个封装的控制台替代方案,但这与原始问题并没有太大关系... - mike652638
谢谢 :) 即使与原问题无关,您仍然可以展示您所做的事情,以便未来寻找自定义样式控制台的人可以复制和编辑您的代码。也许他们会给您点赞 :) 顺便说一句,当我回答这个问题时,我没有想到这种用法 ;) - Ludovic Feltz
根据您的建议,我已经将其作为新答案发布了,谢谢兄弟 :) - mike652638

8
你可以像这样做:

你可以有这样的东西:

console.error = (function() {
    var error = console.error;

    return function(exception) {
        if (typeof exception.stack !== 'undefined') {
            error.call(console, exception.stack);
        } else {
            error.apply(console, arguments);
        }
    }
})();

2
我刚刚修改了你的代码,如果你在使用 typeof exception.stack 之前检查一下 exception 是否为对象且不为 null,那么代码会更好,否则可能会出现异常。 - ZER0

2

受@Ludovic Feltz回答的启发,我找到了一个带有自定义样式的封装控制台的替代方案。

虽然这个答案与原问题关系不大,但正如Ludovic在上面的评论中建议的那样,我将其发布在这里,希望能帮助那些也想使用首选样式自定义/覆盖控制台的人们 :)

注意:您可能需要打开浏览器控制台(默认按F12键)才能在下面点击“运行代码段”后看到结果。

window.msg = (function (defaultConsole) {
  return Object.assign({}, defaultConsole, {
    log(text) {
      defaultConsole.log("%cLOG: %c" + text,
        "background-color: #fff; color: #5CB85C; font-weight: bold; padding-left: 8px; font-size: 1.2em",
        "background-color: #5CB85C; color: #fff; font-weight: bold; padding: 0 8px; font-size: 1.2em");
    },
    info(text) {
      defaultConsole.info("%cINFO: %c" + text,
        "background-color: #fff; color: #337AB7; font-weight: bold; padding-left: 8px; font-size: 1.2em",
        "background-color: #337AB7; color: #fff; font-weight: bold; padding: 0 8px; font-size: 1.2em");
    },
    warn(text) {
      defaultConsole.warn("%cWARN: %c" + text,
        "background-color: #fff; color: #F0AD4E; font-weight: bold; padding-left: 8px; font-size: 1.2em",
        "background-color: #F0AD4E; color: #fff; font-weight: bold; padding: 0 8px; font-size: 1.2em");
    },
    error(text) {
      defaultConsole.error("%cERROR: %c" + text,
        "background-color: #fff; color: #D9534F; font-weight: bold; padding-left: 8px; font-size: 1.2em",
        "background-color: #D9534F; color: #fff; font-weight: bold; padding: 0 8px; font-size: 1.2em");
    }
  })
}(window.console));

msg.log('Log Message !');
msg.info('Info Message !');
msg.warn('Warn Message !');
msg.error('Error Message !');
msg.debug('Debug Message !');
msg.dir('Dir Message !');

/*Note: 1).If we assign the above to console instead of msg, the default console.log, console.info, etc would be overridden with custom styles;
        2).The above methods have utilized some ES6 features which may not be compatiable with old browsers, check below for ES5 version;
*/

//The ES5 Version
window.msg2 = (function (defaultConsole) {
  //The for loop within default console is to inherit all methods from it so that the uncustomized methods like msg2.debug(), msg2.dir(), etc won't throw errors;
  for (var key in defaultConsole) {
    this[key] = defaultConsole[key];
  }
  this.log = function (text) {
    defaultConsole.log("%cLOG: %c" + text,
      "background-color: #fff; color: #5cb85c; font-weight: bold; padding-left: 8px; font-size: 1.2em",
      "background-color: #5cb85c; color: #fff; font-weight: bold; padding: 0 8px; font-size: 1.2em");
  };
  this.info = function (text) {
    defaultConsole.info("%cINFO: %c" + text,
      "background-color: #fff; color: #337ab7; font-weight: bold; padding-left: 8px; font-size: 1.2em",
      "background-color: #337ab7; color: #fff; font-weight: bold; padding: 0 8px; font-size: 1.2em");
  };
  this.warn = function (text) {
    defaultConsole.warn("%cWARN: %c" + text,
      "background-color: #fff; color: #f0ad4e; font-weight: bold; padding-left: 8px; font-size: 1.2em",
      "background-color: #f0ad4e; color: #fff; font-weight: bold; padding: 0 8px; font-size: 1.2em");
  };
  this.error = function (text) {
    defaultConsole.error("%cERROR: %c" + text,
      "background-color: #fff; color: #d9534f; font-weight: bold; padding-left: 8px; font-size: 1.2em",
      "background-color: #d9534f; color: #fff; font-weight: bold; padding: 0 8px; font-size: 1.2em");
  }
  return this;
}(window.console));

msg2.log('Log Message !');
msg2.info('Info Message !');
msg2.warn('Warn Message !');
msg2.error('Error Message !');
msg2.debug('Debug Message !');
msg2.dir('Dir Message !');


//My Original Answer is as below, which seemed simpler and more readable, however, the uncustomized methods like msg3.debug(), msg3.dir(), etc would throw errors such as 'msg3.debug is not a function';
window.msg3 = (function (defaultConsole) {
  return {
    log: function (text) {
      defaultConsole.log("%cLOG: %c" + text,
        "background-color: #fff; color: #5CB85C; font-weight: bold; padding-left: 8px; font-size: 1.2em",
        "background-color: #5CB85C; color: #fff; font-weight: bold; padding: 0 8px; font-size: 1.2em");
    },
    info: function (text) {
      defaultConsole.info("%cINFO: %c" + text,
        "background-color: #fff; color: #337AB7; font-weight: bold; padding-left: 8px; font-size: 1.2em",
        "background-color: #337AB7; color: #fff; font-weight: bold; padding: 0 8px; font-size: 1.2em");
    },
    warn: function (text) {
      defaultConsole.warn("%cWARN: %c" + text,
        "background-color: #fff; color: #F0AD4E; font-weight: bold; padding-left: 8px; font-size: 1.2em",
        "background-color: #F0AD4E; color: #fff; font-weight: bold; padding: 0 8px; font-size: 1.2em");
    },
    error: function (text) {
      defaultConsole.error("%cERROR: %c" + text,
        "background-color: #fff; color: #D9534F; font-weight: bold; padding-left: 8px; font-size: 1.2em",
        "background-color: #D9534F; color: #fff; font-weight: bold; padding: 0 8px; font-size: 1.2em");
    }
  };
}(window.console));
msg3.log('Log Message !');
msg3.info('Info Message !');
msg3.warn('Warn Message !');
msg3.error('Error Message !');
msg3.debug('Debug Message !');
msg3.dir('Dir Message !');


1

try this:

var console={
    log: function(v){
        alert(v);
    }
};
console.log('hello world');

UPD:
检查此内容:
var originalConsole={
    log: (function(c){
        return function(v){
            c.log(v);
        };
    }(window.console))
};
var console={
    log: function(v){
        originalConsole.log('_original_');
        originalConsole.log(v);
    }
};
console.log('hello world');

originalConsole 存储原始 console 对象所需的方法(在我的示例中仅为 log),然后使用新对象覆盖 console

UPD2

var console=(function(c){
    return {
        log: function(v){
            c.log('_original_');
            c.log(v);
        }
    };
}(window.console));
console.log('hello world');

我希望这能帮到你。


谢谢,但我不想要一个警报,我想在控制台中打印。 - Charles
@charles:好的,所以你想用新的替换原来的“console”,并从新的中调用原始的。是这样吗? - Ruslan Polutsygan
谢谢,我用这种方式做了,但是我想避免使用另一个变量... 我认为这是不可能的。 - Charles
@charles:我看到你已经选择了最佳答案,但无论如何:)请查看我的帖子中的upd2。可以避免使用额外变量。JavaScript创造奇迹:)原始的console可以通过函数内部的c变量访问。对于外部世界,console可以是任何你想要的 :)干杯! - Ruslan Polutsygan
@charles:我相信这是因为 console.log 是原生 JS 函数。如果我们尝试用可以访问旧版本的"自定义"函数来重写它,那么它将会起作用。可以在此处查看演示- http://jsfiddle.net/u7kFP/。所以,似乎你必须覆盖整个 console,并明确说明它应该从原始函数中获取哪些函数。可以在此处查看演示- http://jsfiddle.net/Fw68C/1/。 - Ruslan Polutsygan
显示剩余2条评论

1
你正在调用window对象上的console.log函数。你应该在console对象上调用它。
console.log = function() {
  this.apply(console, arguments);
}.bind(console.log);

console.log('as');

0

我建议使用:https://github.com/sunnykgupta/jsLogger

特点:

  1. 它安全地覆盖了console.log。
  2. 如果控制台不可用,它会进行处理(是的,您也需要考虑这一点)。
  3. 存储所有日志(即使它们被抑制)以供以后检索。
  4. 处理主要的控制台函数,如logwarnerrorinfo

可以进行修改,并将在出现新建议时进行更新。

免责声明:我是该插件的作者。


0
一个小点... console.log 可以接收多个参数,例如:
console.log('results', result1, result2, result3);

如果你想要这种行为,你可以像这样做:
console.log = function(){
    var args = Array.from(arguments).join(' ');
    ...
}

0

仅仅是增强之前@Ludovic的回答,使他的回答也支持nodejs

// define a new console
var console=(function(oldCons){
    return {
        log: function(text){
            oldCons.log(text);
            // Your code
        },
        info: function (text) {
            oldCons.info(text);
            // Your code
        },
        warn: function (text) {
            oldCons.warn(text);
            // Your code
        },
        error: function (text) {
            oldCons.error(text);
            // Your code
        }
    };
}(global.console !== undefined ? global.console : window.console));

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