在你的生产JavaScript代码中保留“console.log()”调用是个不好的主意吗?

82

我在JavaScript代码中有很多console.log()调用。

在部署到生产环境之前,我应该注释掉它们吗?

我希望将它们保留在那里,这样如果需要进行任何调试,就不必再添加注释。这是一个坏主意吗?


1
对于那些寻找 Angular 版本的此问题的人,请访问:https://dev59.com/uVgQ5IYBdhLWcg3wvGUY - rmcsharry
如何以及为什么在生产环境中禁用控制台日志输出。相关文章链接:https://medium.com/@hfally/deactivate-console-log-on-production-why-and-how-d0345abbe71 - surfmuggle
12个回答

121

这会导致Javascript错误,终止包含错误的Javascript代码块的执行。

然而,你可以定义一个虚拟函数,当Firebug未启用时它是一个无操作函数:

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

如果你使用的是log以外的方法,那么你也需要将这些方法进行存根处理。


谢谢。看起来这是一个不错的解决方法。让我看看我是否理解了它。你的意思是,如果控制台未定义,则将控制台设置为空函数。我不明白“log”后面的冒号语法。那是做什么的?为什么在“console=”后面的大括号里面? - Charlie Kotter
2
花括号定义了一个对象字面量:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Grammar_and_Types#Object_literals,而“function() {}”部分则定义了一个不带参数且什么也不做的匿名函数。尽管如此,在调用“console.log(foo)”时仍然可以传递参数,因为JS并不在意您是否使用过多或过少的参数来调用函数。 - Jason C
1
非常棒的解决方案! :-) 我前几天也遇到了这个问题。我的页面只在 FireBug 打开时在 FF 中工作,并且在 IE 中某些操作上会随机停止。我当时就像是怎么回事?!然后,我意识到我仍然在使用 console.log 调用,所以我必须去除它们。现在我可能会将您的解决方案添加到我的主 JS 文件中,再也不必担心这种不幸的情况了。 - KyleFarris
6
我有一个小项目(经过单元测试),可以帮助你使用尽可能少的代码来完成各种不同的控制台方法。它在这里:https://github.com/andyet/ConsoleDummy.js - Henrik Joreteg
对于其他人来说可能很琐碎,但是如果有人想知道什么时候console会变成undefined,答案是当你“自己”这样做的时候。 - aderchox

37

正如其他人已经指出的那样,保留它将会在某些浏览器中导致错误,但是这些错误可以通过添加一些存根来解决。

然而,我不仅会注释掉它们,而且会直接删除这些行。否则似乎有点马虎。也许我有点迂腐,但我认为“生产”代码根本不应包含任何“调试”代码,即使以注释形式存在也不应该。如果您保留注释,则这些注释应描述代码正在做什么或背后的原因,而不是禁用的代码块。(尽管大多数注释应该由您的缩小过程自动删除。您在进行缩小吗?)

此外,在几年的JavaScript工作中,我无法回忆起曾经回到一个函数并说:“天啊,我希望我在这里留下那些console.logs!”通常情况下,当我完成对函数的工作,并且稍后必须回到该函数时,我是为了解决其他问题而回来的。无论新问题是什么,如果以前一轮工作中的console.logs可能有所帮助,那么我第一次就能发现问题。换句话说,如果我回到某件事上,我不太可能需要与以前完全相同的调试信息。

这只是我的个人意见,祝好运!


13年后的更新

我改变了主意,并现在同意多年来累积的评论。

某些日志消息为应用程序提供长期价值,即使是客户端JavaScript应用程序,也应该保留。

其他日志消息是低价值噪音,应该被删除,否则它们将淹没高价值消息。


1
问题通常在生产周期中出现,当某些东西正在被调试或测试时,人们会在开发团队之外查看它,这些人没有开发控制台。我个人的偏好是不让应用程序在他们身上死掉,这样我们就不会收到像“你们的新代码对我没有任何作用”这样的电话。 - Dimitar Christoff
11
永久性的调试行非常棒。它们意味着你通常不必四处寻找错误源头,而可以立即看到发生了什么。在许多代码区域,日志记录语句并不会对性能造成任何显著影响。 - Casebash
4
良好的日志记录应该有多种用途。说log()语句只对调试一个问题有用,让我想起了那些不知道如何编写正确日志记录的人在Java中进行日志记录。 - Thomas W
7
简而言之:记录重要的(高级别)决策和事件处理,以便可以跟踪业务、高级别UI和主要事件处理流程。这些对于开发应用程序是非常有价值的。然而,“进入方法A”、“离开方法A”、“参数1 77”的日志记录则不好。 - Thomas W

10
据我所知,没有比以下45个字符更短的方法来存根console.log
window.console||(console={log:function(){}});

这是三个不同版本中的第一个,具体取决于您要存根哪些控制台方法,它们都非常简洁,并且已在IE6+和现代浏览器中进行了测试。
另外两个版本涵盖其他不同的控制台方法。其中一个版本包含四个基本方法,另一个版本则包含firebug和webkit的所有已知控制台方法。同样,在最小的文件大小下实现。
该项目托管在github上:https://github.com/andyet/ConsoleDummy.js 如果您有任何想法以进一步减少代码量,请随时贡献。
- 编辑 - 2012年5月16日
我已经改进了这段代码。它仍然很小,但增加了打开和关闭控制台输出的功能:https://github.com/HenrikJoreteg/andlog 它被 The Changelog Show推荐。

10
如果您拥有部署脚本,那么您可以使用它来删除对console.log的调用(并且可以缩小文件大小)。
在此过程中,您可以使用JSLint检查您的JS代码并记录违规内容以供检查(或防止部署)。
这是自动化部署的好处之一。如果您的流程允许发布带有console.log的js文件,在某个时候,您 必须 这样做。

5

如果对象不存在,您至少应该创建一个虚拟的console.log,这样您的代码就不会在没有安装firebug的用户机器上抛出错误。

另一种可能性是仅在“调试模式”下触发日志记录,即如果设置了某个标志:

if(_debug) console.log('foo');
_debug && console.log('foo');

同意Cristoph的看法,在Safari中不会有问题,但在其他浏览器中会抛出错误,并可能停止javascript继续运行。总体上不是一个好主意... - Sinan

5
希望对某些人有所帮助--我以前写了一个包装器,比被接受的解决方案稍微灵活一些。
显然,如果您使用其他方法,例如console.info等,您可以复制该效果。当您完成分阶段环境时,只需将默认的C.debug更改为false以进行生产,您就不必更改任何其他代码/删除行等。非常容易回来后调试。
var C = {
    // console wrapper
    debug: true, // global debug on|off
    quietDismiss: false, // may want to just drop, or alert instead
    log: function() {
        if (!C.debug) return false;

        if (typeof console == 'object' && typeof console.log != "undefined") {
            console.log.apply(this, arguments); 
        }
        else {
            if (!C.quietDismiss) {
                var result = "";
                for (var i = 0, l = arguments.length; i < l; i++)
                    result += arguments[i] + " ("+typeof arguments[i]+") ";

                alert(result);
            }
        }
    }
}; // end console wrapper.

// example data and object
var foo = "foo", bar = document.getElementById("divImage");
C.log(foo, bar);

// to surpress alerts on IE w/o a console:
C.quietDismiss = true;
C.log("this won't show if no console");

// to disable console completely everywhere:
C.debug = false;
C.log("this won't show ever");

4

这对我来说似乎是有效的...

if (!window.console) {
    window.console = {
        log: function () {},
        group: function () {},
        error: function () {},
        warn: function () {},
        groupEnd: function () {}
    };
}

3

我觉得我可以分享一种不同的看法。在PCI应用程序中将这种类型的输出暴露给外部世界会使你不符合规定。


从没想到过。谢谢。 - Charlie Kotter
他可能指的是http://en.wikipedia.org/wiki/Payment_Card_Industry_Data_Security_Standard... - Simon East
2
当有人右击你的网站查看源代码时,这会使你不符合规定吗? - dwlz

2

我认为控制台桩是一种好的方法。我尝试过各种控制台插件、代码片段,包括一些相当复杂的插件。但它们在至少一个浏览器中都存在问题,所以我最终选择了以下简单的方法,这是其他代码片段和YUI团队的建议的汇集。它似乎可以在IE8+、Firefox、Chrome和Safari(Windows版)中运行。

// To disable logging when posting a production release, just change this to false.
var debugMode = false;

// Support logging to console in all browsers even if the console is disabled. 
var log = function (msg) {
    debugMode && window.console && console.log ? console.log(msg) : null;
};

注意:它支持通过标志禁用将日志记录到控制台。也许您可以通过构建脚本自动化此过程。或者,您可以在运行时公开UI或其他机制来翻转此标志。当然,您可以更加复杂,使用日志级别,基于日志阈值的日志ajax提交(例如,所有错误级别语句都传输到服务器进行存储等)。
许多关于日志记录的线程/问题似乎认为日志语句是调试代码而不是代码仪器化。因此希望删除日志语句。当应用程序处于野外环境中时,仪器化非常有用,而且不能像从调试器中获取信息那样容易。无论日志记录到何处,都不应记录任何敏感信息,因此不应损害隐私/安全性。一旦您将日志记录视为仪器化,它现在就成为生产代码,并且应该按同样的标准编写。
随着应用程序使用越来越复杂的javascript,我认为仪器化至关重要。

1

正如其他人所提到的,在大多数浏览器中将会抛出错误。在Firefox 4中,它不会抛出错误,消息会被记录在Web开发者控制台中(Firefox 4中新增)。

一个我真的很喜欢的解决此类错误的方法是 de&&bug

var de = true;
var bug = function() { console.log.apply(this, arguments); }

// within code
de&&bug(someObject);

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