如何在Google Chrome的JavaScript控制台中打印调试信息?

478

如何在Google Chrome的JavaScript控制台中打印调试信息?

请注意,JavaScript控制台与JavaScript调试器不同;它们具有不同的语法(据我所知),因此JavaScript调试器中的print命令在这里不起作用。在JavaScript控制台中,print()将参数发送到打印机。

15个回答

605

在浏览器地址栏中执行以下代码:

javascript: console.log(2);

可以成功地将消息打印到 Google Chrome 中的“JavaScript Console”。


13
刚刚意识到,console.log() 对于 JavaScript 调试非常好用... 在实践中我经常忘记使用它。 - Ish
这些“输出”中的一个可以有多长?顺便点个赞,这真的很有帮助。 - nbura
3
@dbrin,这对于开发来说是可以的,但是在部署之前,任何console.log()代码都应该从生产代码中删除。 - Samuel MacLachlan
2
在部署之前,应该从生产代码中删除 Console.Log,因为如果不这样做,这些消息将记录到用户的 JavaScript 控制台中。虽然他们不太可能看到它,但它会占用他们设备上的内存空间。此外,根据 Log 的内容,您有可能向人们透露如何黑客/反向工程您的应用程序。 - Samuel MacLachlan

167

在Andru的想法基础上进行改进,您可以编写一个脚本,用于创建控制台函数(如果它们不存在):

if (!window.console) console = {};
console.log = console.log || function(){};
console.warn = console.warn || function(){};
console.error = console.error || function(){};
console.info = console.info || function(){};

然后,使用以下任一方法:

console.log(...);
console.error(...);
console.info(...);
console.warn(...);

这些函数将记录不同类型的项目(可以根据日志、信息、错误或警告进行过滤),并且在控制台不可用时不会导致错误。这些函数将在Firebug和Chrome控制台中工作。


谢谢你的建议。如果你只运行一次“if”语句,像这样if (!window.console) {然后把所有东西放在括号里面,代码不会更紧凑吗?现在你正在评估相同的内容四次。 - Dan Rosenstark
不行,因为仅仅拥有window.console并不能保证你拥有window.console.log或者.warn等。 - Paul
18
请注意,如果此脚本在页面加载时已经被载入且控制台窗口未打开,则它会创建一个“虚拟”控制台。如果你在页面加载后再打开控制台,这可能会阻止真正的控制台起作用。(至少在旧版本的Firefox/Firebug和Chrome中是这样) - cwd
1
我有补充,见下面的 我的回答 - Tim Büthe
这会导致Chrome出现“TypeError: Illegal Invocation”错误。请参见https://dev59.com/uGsz5IYBdhLWcg3wBzbi。 - geira
1
不,这不会导致chrome出现TypeError错误。上面链接的问题是关于使用“this”进行调用的。上面的代码并没有这样做,在Chrome中可以正常工作。 - gman

49

只需添加一个很酷的功能,许多开发者都会错过:

console.log("this is %o, event is %o, host is %s", this, e, location.host);

这是一个神奇的%o转储,可点击和深度浏览JavaScript对象的内容。%s仅用于记录。

还有这个也很酷:

console.log("%s", new Error().stack);

输出类似Java的堆栈跟踪信息直到new Error()的调用点(包括文件路径和行号!)。

%onew Error().stack在Chrome和Firefox中都可用!

对于Firefox中的堆栈跟踪,也可以使用:

console.trace();

正如https://developer.mozilla.org/en-US/docs/Web/API/console所说。

愉快的黑客!

更新: 一些库是由不好的人编写的,他们重新定义console对象以满足自己的目的。在加载库后恢复原始的浏览器console,请使用:

delete console.log;
delete console.warn;
....

请查看 Stack Overflow 问题 Restoring console.log()


3
我刚刚发现的另一个方法是:console.dir。https://developer.mozilla.org/en-US/docs/Web/API/console.dir - dbrin

17
这里是一个简短的脚本,用于检查控制台是否可用。如果不可用,则尝试加载Firebug,如果Firebug也不可用,则加载Firebug Lite。现在您可以在任何浏览器中使用console.log。享受吧!
if (!window['console']) {

    // Enable console
    if (window['loadFirebugConsole']) {
        window.loadFirebugConsole();
    }
    else {
        // No console, use Firebug Lite
        var firebugLite = function(F, i, r, e, b, u, g, L, I, T, E) {
            if (F.getElementById(b))
                return;
            E = F[i+'NS']&&F.documentElement.namespaceURI;
            E = E ? F[i + 'NS'](E, 'script') : F[i]('script');
            E[r]('id', b);
            E[r]('src', I + g + T);
            E[r](b, u);
            (F[e]('head')[0] || F[e]('body')[0]).appendChild(E);
            E = new Image;
            E[r]('src', I + L);
        };
        firebugLite(
            document, 'createElement', 'setAttribute', 'getElementsByTagName',
            'FirebugLite', '4', 'firebug-lite.js',
            'releases/lite/latest/skin/xp/sprite.png',
            'https://getfirebug.com/', '#startOpened');
    }
}
else {
    // Console is already available, no action needed.
}

17

快速提醒一下 - 如果您想在不删除所有console.log()的情况下在Internet Explorer中进行测试,您需要使用Firebug Lite ,否则您将会得到一些并不友好的错误。

(或者创建自己的console.log()函数,只返回false即可。)


2
我避免跨浏览器错误,例如:if (console) console.log()。 - Craig Wohlfeil
如果您在IE中打开开发人员工具(F12),则会创建console对象,并存在直到您关闭该浏览器实例。 - Tim Büthe

13
除了Delan Azabani的回答之外,我想分享我的console.js,并且我用它来达到同样的目的。我使用函数名的数组创建一个空的控制台,我认为这是一种非常方便的方法,并且我处理了Internet Explorer,它有一个console.log函数,但没有console.debug
// Create a noop console object if the browser doesn't provide one...
if (!window.console){
  window.console = {};
}

// Internet Explorer has a console that has a 'log' function, but no 'debug'. To make console.debug work in Internet Explorer,
// We just map the function (extend for info, etc. if needed)
else {
  if (!window.console.debug && typeof window.console.log !== 'undefined') {
    window.console.debug = window.console.log;
  }
}

// ... and create all functions we expect the console to have (taken from Firebug).
var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
    "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];

for (var i = 0; i < names.length; ++i){
  if(!window.console[names[i]]){
    window.console[names[i]] = function() {};
  }
}

12

或者使用这个函数:

function log(message){
    if (typeof console == "object") {
        console.log(message);
    }
}

console.constructor === Object && (log = m => console.log(m)) - vhs

7
这是我的控制台包装器类,它可以输出范围以使生活更轻松。请注意使用 localConsole.debug.call(),以便localConsole.debug在调用类的范围内运行,从而提供对其toString方法的访问。
localConsole = {

    info: function(caller, msg, args) {
        if ( window.console && window.console.info ) {
            var params = [(this.className) ? this.className : this.toString() + '.' + caller + '(), ' + msg];
            if (args) {
                params = params.concat(args);
            }
            console.info.apply(console, params);
        }
    },

    debug: function(caller, msg, args) {
        if ( window.console && window.console.debug ) {
            var params = [(this.className) ? this.className : this.toString() + '.' + caller + '(), ' + msg];
            if (args) {
                params = params.concat(args);
            }
            console.debug.apply(console, params);
        }
    }
};

someClass = {

    toString: function(){
        return 'In scope of someClass';
    },

    someFunc: function() {

        myObj = {
            dr: 'zeus',
            cat: 'hat'
        };

        localConsole.debug.call(this, 'someFunc', 'myObj: ', myObj);
    }
};

someClass.someFunc();

这会在Firebug中产生以下输出:
In scope of someClass.someFunc(), myObj: Object { dr="zeus", more...}

或者使用Chrome:
In scope of someClass.someFunc(), obj:
Object
cat: "hat"
dr: "zeus"
__proto__: Object

6
我个人使用类似于tarek11011的这个东西:
// Use a less-common namespace than just 'log'
function myLog(msg)
{
    // Attempt to send a message to the console
    try
    {
        console.log(msg);
    }
    // Fail gracefully if it does not exist
    catch(e){}
}

重点是,除了直接把console.log()放入JavaScript代码之外,至少有一些记录其他内容的实践是个好主意。因为如果你忘记了它,并且它在生产站点上,则可能会破坏该页面的所有JavaScript代码。


为什么不使用 if(windows.console) console.log(msg) 呢? - JimmyMcHoover
你的意思是 window.console。唯一有用的时候是当抛出错误(如果 console.log 不是一个函数)时,try 才会有用,因为 console 被重新定义了。使用 window.console && window.console.log instanceof Function 会更有用。 - Aram Kocharyan

4
我遇到了很多开发人员在代码中加入console.()语句的问题。而且,我真的不喜欢调试Internet Explorer,尽管Internet Explorer 10Visual Studio 2012等工具有很大改进。
因此,我重写了console对象本身...我添加了一个__localhost标志,只允许在本地主机上使用console语句。我还向Internet Explorer添加了console.()函数(会弹出一个alert())。
// Console extensions...
(function() {
    var __localhost = (document.location.host === "localhost"),
        __allow_examine = true;

    if (!console) {
        console = {};
    }

    console.__log = console.log;
    console.log = function() {
        if (__localhost) {
            if (typeof console !== "undefined" && typeof console.__log === "function") {
                console.__log(arguments);
            } else {
                var i, msg = "";
                for (i = 0; i < arguments.length; ++i) {
                    msg += arguments[i] + "\r\n";
                }
                alert(msg);
            }
        }
    };

    console.__info = console.info;
    console.info = function() {
        if (__localhost) {
            if (typeof console !== "undefined" && typeof console.__info === "function") {
                console.__info(arguments);
            } else {
                var i, msg = "";
                for (i = 0; i < arguments.length; ++i) {
                    msg += arguments[i] + "\r\n";
                }
                alert(msg);
            }
        }
    };

    console.__warn = console.warn;
    console.warn = function() {
        if (__localhost) {
            if (typeof console !== "undefined" && typeof console.__warn === "function") {
                console.__warn(arguments);
            } else {
                var i, msg = "";
                for (i = 0; i < arguments.length; ++i) {
                    msg += arguments[i] + "\r\n";
                }
                alert(msg);
            }
        }
    };

    console.__error = console.error;
    console.error = function() {
        if (__localhost) {
            if (typeof console !== "undefined" && typeof console.__error === "function") {
                console.__error(arguments);
            } else {
                var i, msg = "";
                for (i = 0; i < arguments.length; ++i) {
                    msg += arguments[i] + "\r\n";
                }
                alert(msg);
            }
        }
    };

    console.__group = console.group;
    console.group = function() {
        if (__localhost) {
            if (typeof console !== "undefined" && typeof console.__group === "function") {
                console.__group(arguments);
            } else {
                var i, msg = "";
                for (i = 0; i < arguments.length; ++i) {
                    msg += arguments[i] + "\r\n";
                }
                alert("group:\r\n" + msg + "{");
            }
        }
    };

    console.__groupEnd = console.groupEnd;
    console.groupEnd = function() {
        if (__localhost) {
            if (typeof console !== "undefined" && typeof console.__groupEnd === "function") {
                console.__groupEnd(arguments);
            } else {
                var i, msg = "";
                for (i = 0; i < arguments.length; ++i) {
                    msg += arguments[i] + "\r\n";
                }
                alert(msg + "\r\n}");
            }
        }
    };

    /// <summary>
    /// Clever way to leave hundreds of debug output messages in the code,
    /// but not see _everything_ when you only want to see _some_ of the
    /// debugging messages.
    /// </summary>
    /// <remarks>
    /// To enable __examine_() statements for sections/groups of code, type the
    /// following in your browser's console:
    ///       top.__examine_ABC = true;
    /// This will enable only the console.examine("ABC", ... ) statements
    /// in the code.
    /// </remarks>
    console.examine = function() {
        if (!__allow_examine) {
            return;
        }
        if (arguments.length > 0) {
            var obj = top["__examine_" + arguments[0]];
            if (obj && obj === true) {
                console.log(arguments.splice(0, 1));
            }
        }
    };
})();

使用示例:

    console.log("hello");

Chrome/Firefox:

    prints hello in the console window.

互联网浏览器:

    displays an alert with 'hello'.

对于那些仔细查看代码的人,你会发现console.examine()函数。我几年前创建了它,以便在产品的某些区域留下调试代码,以帮助解决QA/客户问题。例如,我会在一些发布的代码中留下以下行:
    function doSomething(arg1) {
        // ...
        console.examine("someLabel", arg1);
        // ...
    }

然后从发布的产品中,在控制台(或前缀为“javascript:”的地址栏)中键入以下内容:

    top.__examine_someLabel = true;

然后,我将看到所有已记录的console.examine()语句。它在很多时候都是非常有帮助的。


感谢这个精彩的想法,它非常鼓舞人心。从你的 examine 函数开始,我无意中想到了 PHP 调试范围的概念。现在我可以为 PHP 代码打开/关闭主题选择性调试和日志记录。就像常规的 Linux 程序一样,它可以以标准的 verbose 等风格进行日志记录。这确实是一个不错的想法! - Johan

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