Javascript 如何安全地包装`console.log`?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8785624/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 07:30:05  来源:igfitidea点击:

How to safely wrap `console.log`?

javascriptinternet-explorerconsoleloggingwrapper

提问by Dagg Nabbit

Suppose I want to include some calls to console.logfor some legitimate production reason, say for something like a unit test harness. Obviously I would not want this to throw a premature exception if the browser doesn't have a console, or if no console is present.

假设我想包含一些console.log出于合法生产原因的调用,比如单元测试工具。显然,如果浏览器没有console,或者没有控制台,我不希望这会引发过早的异常。

What's the best way to create a simple logfunction to log stuff to the console, or silently fail without error if no console is present?

创建一个简单的log函数来将内容记录到控制台的最佳方法是什么,或者如果没有控制台,则无提示地失败而没有错误?

The accepted answer to the question linked above:

上面链接的问题的公认答案:

var log = Function.prototype.bind.call(console.log, console);
log.apply(console, ["this", "is", "a", "test"]);
var log = Function.prototype.bind.call(console.log, console);
log.apply(console, ["this", "is", "a", "test"]);

Can this logfunction be called normally on IE, and the use of applyhere is just to show it's possible? And, I assume from the linked question that this will fail if IE's console is closed when it runs, so logwon't work even after the console opens, correct? If that's wrong, can someone explain how it works?

这个log函数在IE上可以正常调用apply吗,这里的使用只是为了说明可以吗?而且,我从链接的问题中假设,如果 IE 的控制台在运行时关闭,这将失败,因此log即使在控制台打开后也无法工作,对吗?如果这是错误的,有人可以解释它是如何工作的吗?

This ycombinator articleseems relevant. Are they are talking about the same IE behavior as the question linked above?

这篇ycombinator 文章似乎很相关。他们是否在谈论与上面链接的问题相同的 IE 行为?

Function.prototype.apply.apply(console.log, [console, arguments]);

Works both on IE9 broken console.log, and regular console.log from other vendors. Same hack as using Array.prototype.slice to convert arguments into a real array.

Function.prototype.apply.apply(console.log, [console, arguments]);

适用于 IE9 损坏的 console.log 和来自其他供应商的常规 console.log。与使用 Array.prototype.slice 将参数转换为真实数组的技巧相同。

This works nicely in my chrome console.

这在我的 chrome 控制台中运行良好。

function echo(){
  Function.prototype.apply.apply(console.log, [console, arguments]);
}

Simplified:

简化:

function echo(){
  Function.apply.call(console.log, console, arguments);
}

Add a check and return:

添加检查并返回:

function echo(){
  return window.console && console.log &&
         Function.apply.call(console.log, console, arguments);
}

The example above looks adequate to me. I don't have IE on hand to test it, though. Is this a reasonable approach for safely wrapping console.log?

上面的例子对我来说已经足够了。不过,我手头没有 IE 来测试它。这是安全包装的合理方法console.log吗?



More questions

更多问题

Following the link in nav's answer below, we see the code:

按照下面导航的答案中的链接,我们可以看到代码:

Function.prototype.call.call(console.log, console,
    Array.prototype.slice.call(arguments));

What is the purpose of converting argumentsto an array in this case? I guess it must fail in some browser if you don't do this? And, opera weird behavior and console-less browsers aside, shouldn't something like this pretty much work for every other browser as well? And does prototypeserve a purpose in the above examples, or are we just being pedantic... Function.call.callor Object.call.callor for that matter isNaN.call.callseem to work just as well as Function.prototype.call.call.

arguments在这种情况下转换为数组的目的是什么?如果您不这样做,我想它一定会在某些浏览器中失败?而且,除了奇怪的行为和无控制台的浏览器之外,这样的事情不应该也适用于所有其他浏览器吗?并且确实prototype在上述示例中起到了作用,或者我们只是迂腐……Function.call.call或者Object.call.call就此而言isNaN.call.call似乎与Function.prototype.call.call.

采纳答案by Andy E

Can this log function be called normally on IE, and the use of apply here is just to show it's possible?

这个日志函数在IE上能正常调用吗,这里用apply只是为了说明可以吗?

Yes, and yes. That particular example was aimed squarely at the "is it a real function"part of the linked question.

是的,是的。该特定示例直接针对链接问题的“它是一个真正的功能”部分。

And, I assume from the linked question that this will fail if IE's console is closed when it runs, so log won't work even after the console opens, correct?

而且,我从链接的问题中假设,如果 IE 的控制台在运行时关闭,这将失败,因此即使在控制台打开后日志也不会工作,对吗?

Correct. As explained in my answer on that question, the consoleobject is not exposed until the first time the developer tools are opened for a particular tab. Most developers use a console shim, in which case the Function#bindapproach becomes a little obsolete because you may as well use the Function#apply.applymethod.

正确的。正如我在该问题上的回答中所解释的那样,console直到第一次为特定选项卡打开开发人员工具时,才会公开该对象。大多数开发人员使用控制台填充程序,在这种情况下,该Function#bind方法有点过时了,因为您也可以使用该Function#apply.apply方法。

What is the purpose of converting arguments to an array in this case?

在这种情况下将参数转换为数组的目的是什么?

There isn't one, it's redundant. Unless it's a custom logimplementation, in which case the developer may have a reason to convert an arguments object to an array.

没有,是多余的。除非它是自定义日志实现,在这种情况下,开发人员可能有理由将参数对象转换为数组。

And does prototype serve a purpose in the above examples, or are we just being pedantic...

原型在上面的例子中是否有用,或者我们只是在迂腐......

Well, yes and no. Some developer may have unwittingly changed Function.callto a custom function or value. Of course, they could break Function.prototype.calltoo, but this is far less likely to happen by accident.

嗯,是和不是。某些开发人员可能会在不知不觉中更改Function.call为自定义函数或值。当然,它们也可能破裂Function.prototype.call,但这种意外发生的可能性要小得多。

回答by dbrin

The problem with wrappers is that they will obfuscate file name and line number of the source of the log message.

包装器的问题在于它们会混淆日志消息源的文件名和行号。

Simple IE7 and below shim that preserves Line Numbering for other browsers:

为其他浏览器保留行编号的简单 IE7 及以下垫片:

/* console shim*/
(function () {
    var f = function () {};
    if (!window.console) {
        window.console = {
            log:f, info:f, warn:f, debug:f, error:f
        };
    }
}());

回答by ChrisN

Sorry, there was a bug in my post. Don't know how I missed it.

抱歉,我的帖子中有一个错误。不知道我是怎么错过的。

The PROPER way to create a global console object, if it does not exist:

创建全局控制台对象的正确方法(如果它不存在):

if (typeof console === "undefined"){
    console={};
    console.log = function(){
        return;
    }
}

回答by etoxin

I like to use:

我喜欢使用:

'console' in window && console.log("Boom!");

It works in all browsers and is easy to understand.

它适用于所有浏览器并且易于理解。

回答by Ammar Hasan

Try using the code snippet below... (this is my preferred approach because it makes you independent of window.console)

尝试使用下面的代码片段...(这是我的首选方法,因为它使您独立于 window.console)

var logger = (function (c) {
    "use strict";
    var m = {
        log: function (a, t) {
            if (!c) { return; /* return or call your custom function here */ }
            var l = c.log,
                f = t === undefined ? l : (this.__dict__[t] || l);
            f.apply(c, a)
        },
        __dict__: {
            "trace": c.trace,
            "debug": c.debug,
            "info": c.info,
            "warn": c.warn,
            "error": c.error
        }
    };

    return {
        trace: function () { m.log(arguments, "trace"); },
        debug: function () { m.log(arguments, "debug"); },
        info: function () { m.log(arguments, "info"); },
        warn: function () { m.log(arguments, "warn"); },
        error: function () { m.log(arguments, "error"); },
        log: function () { m.log(arguments, undefined); }
    };
}(window.console))

So you may now try these in your code and see the result

所以你现在可以在你的代码中尝试这些并查看结​​果

logger.info("Hello");
logger.trace("Hello");
logger.debug("Hello");
logger.warn("Hello");
logger.error("Hello");
logger.log("Hello");

回答by dougajmcdonald

As a slight variation on Chris' answer, simply define 'log' as a property of 'console' with an empty function:

作为 Chris 答案的一个细微变化,只需将 'log' 定义为具有空函数的 'console' 属性:

if (typeof console === "undefined") {
    console = {
        log: function () {
            return;
        } 
   };
}

回答by Антон Баранов

coffeescript:

咖啡脚本:

empty_function = ->
  return
if !window.console?
  window.console = {}
  for fn in ['log', 'info', 'warn', 'debug', 'error']
    if (typeof window.console[fn] isnt 'function')
      window.console[fn] = empty_function

js:

js:

(function() {
  var empty_function, fn, i, len, ref;

  empty_function = function() {};

  if (window.console == null) {
    window.console = {};
    ref = ['log', 'info', 'warn', 'debug', 'error'];
    for (i = 0, len = ref.length; i < len; i++) {
      fn = ref[i];
      if (typeof window.console[fn] !== 'function') {
        window.console[fn] = empty_function;
      }
    }
  }

}).call(this);

回答by Nathan Long

Use Consolation

使用安慰

My ridiculously overengineered console:

我可笑的过度设计的控制台:

  • prevents errors if there's no console
  • prevents logging in production if you left console.logstatements in your code
  • supports console.error, console.group, and all such other methods
  • still gives you backtraces to your log statements
  • 如果没有控制台,则防止错误
  • 如果您console.log在代码中留下语句,则阻止登录生产
  • 支持console.error, console.group, 以及所有其他方法
  • 仍然为您提供日志语句的回溯

It's amazing.

太奇妙了。

But really, you just shouldn't leave consolestatements lying around in your code.

但实际上,您不应该console在代码中留下语句。

Behold and tremble! Presenting: Consolation.js

看,颤抖吧!演示:Consolation.js

回答by Thomas W

Paul Irish has a nice light wrapper/replacement for console.log().

Paul Irish 有一个很好的轻型包装/替代品console.log()

http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/

http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/

Advantages:

好处:

  • Prevent errors if a console isn't around (i.e. IE)
  • Maintains a history of logs, so you can look in the past if your console is added afterwards (e.g. firebug lite)
  • Light & simple.
  • Very quick to type -- log()or window.log().
  • 如果没有控制台(即 IE),则防止错误
  • 维护日志的历史记录,因此您可以在之后添加控制台时查看过去(例如 firebug lite)
  • 轻巧简单。
  • 非常快速地输入 -log()window.log().

回答by Kage

My solution is a little different. I create a standard shortcut for all console.log calls: In my case kag(whatever I want to report in the console).

我的解决方案有点不同。我为所有 console.log 调用创建了一个标准快捷方式:就我而言,kag(无论我想在控制台中报告什么)。

I test for IE, if IE I send the results to an alert box. If Chrome then displays in the console. This also means IE will always work even in console is closed:

我测试 IE,如果 IE,我将结果发送到警报框。如果 Chrome 显示在控制台中。这也意味着 IE 将始终工作,即使在控制台关闭时:

Code:

代码:

var iever = getInternetExplorerVersion();
if(iever>-1){
function kag(params){
    alert(params);
}
} else {
var kag = console.log.bind(console, "REPORT: ");
}

function getInternetExplorerVersion() {
var rv = -1;
if (navigator.appName == 'Microsoft Internet Explorer') {
var ua = navigator.userAgent;
var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
if (re.exec(ua) != null){
  rv = parseFloat( RegExp. );
}
}
return rv;
}