自定义控制台日志功能,一个console.log包装器

时间:2013-12-11 16:34:18

标签: javascript debug-backtrace

function log( msgOrObj ){
    if(dev_mode){
        console.log({
            'message': msgOrObj,
            'caller': arguments.callee.caller.toString()
        });
    }
}

所以,我试图编写一个简单的自定义控制台日志功能(如上所述)。但是我很难找到调用者来自哪个文件和行。我能看到的最多就是调用它的函数。

有没有人做过类似的事情?或者这甚至可能吗?

第70行的somescript.js中使用的示例:

log('some very important message!')

7 个答案:

答案 0 :(得分:4)

是的但它非常hacky并且不能跨浏览器安全。您可以将此作为起点。它borrows from this answer

window.trace = function stackTrace() {
    var err = new Error();
    return err.stack;
}

window.my_log = function (x) {
    var line = trace();
    var lines = line.split("\n");
    console.log(x + " " + lines[2].substring(lines[2].indexOf("("), lines[2].lastIndexOf(")") + 1))
}


window.my_log("What light through yonder window breaks?")

产地:

What light through yonder window breaks? (<anonymous>:2:42) 

答案 1 :(得分:3)

我看到可靠地提取这种信息的唯一方法是抛出一个错误,然后从堆栈跟踪中提取调用者信息,类似于:

function log( msgOrObj ){
    if(dev_mode){

        try {
            in_val_id(); // force an error by calling an non-existent method
        catch(err) {
            // some regex/string manipulation here to extract function name
            // line num, etc. from err.stack
            var caller = ...
            var lineNo = ...
        }

        console.log({
            'message': msgOrObj,
            'caller': caller,
            'lineNo': lineNo
        });
    }
}

Chrome中的堆栈采用以下形式:

ReferenceError: in_val_id is not defined
at log (<anonymous>:4:13)
at <anonymous>:2:14
at <anonymous>:2:28
at Object.InjectedScript._evaluateOn (<anonymous>:581:39)
at Object.InjectedScript._evaluateAndWrap (<anonymous>:540:52)
at Object.InjectedScript.evaluate (<anonymous>:459:21) 

您可以使用以下方法提取函数名称:

caller = err.stack.split('\n')[3].split('at ')[1].split(' (')[0];

在这里使用正则表达式可能会更高效。您可能需要使用不同的方法来使用不同的浏览器提取此信息。

尽管有警告;抛出和处理错误是昂贵的,因此以这种方式输出大量日志消息可能会影响一般性能,但如果它专门用于调试模式则可以接受

答案 2 :(得分:1)

所以,这就是我最终的目的(shout是一个只在dev模式下运行的定制函数):

function log( msgOrObj ){
    if(dev_mode){
        if( typeof(window.console) != 'undefined' ){
            try {  invalidfunctionthrowanerrorplease(); }
            catch(err) {  var logStack = err.stack;  }
            var fullTrace = logStack.split('\n');
            for( var i = 0 ; i < fullTrace.length ; ++i ){
                fullTrace[i] = fullTrace[i].replace(/\s+/g, ' ');
            }
            var caller = fullTrace[1],
                callerParts = caller.split('@'),
                line = '';

            //CHROME & SAFARI
            if( callerParts.length == 1 ){
                callerParts = fullTrace[2].split('('), caller = false;
                //we have an object caller
                if( callerParts.length > 1 ){
                    caller = callerParts[0].replace('at Object.','');
                    line = callerParts[1].split(':');
                    line = line[2];
                }
                //called from outside of an object
                else {
                    callerParts[0] = callerParts[0].replace('at ','');
                    callerParts = callerParts[0].split(':');
                    caller = callerParts[0]+callerParts[1];
                    line = callerParts[2];
                }
            }
            //FIREFOX
            else {
                var callerParts2 = callerParts[1].split(':');
                line = callerParts2.pop();
                callerParts[1] = callerParts2.join(':');
                caller = (callerParts[0] == '') ? callerParts[1] : callerParts[0];
            }
            console.log( ' ' );
            console.warn( 'Console log: '+ caller + ' ( line '+ line +' )' );
            console.log( msgOrObj );
            console.log({'Full trace:': fullTrace });
            console.log( ' ' );
        } else {
            shout('This browser does not support console.log!')
        }
    }
}

log()在应用程序的其余部分之前声明,可以在应用程序内的任何地方调用,并向开发人员提供所需的所有信息,并且不会用完开发模式。

http://webconfiguration.blogspot.co.uk/2013/12/javascript-console-log-wrapper-with.html

答案 3 :(得分:0)

而不是使用你可以做的参数

function log( msg ) {
    if (dev_mode) {
        var e = new Error(msg);
        console.log(e.stack);
    }
}

这将显示调用所有函数的顺序(包括行号和文件)。您可以忽略堆栈的前两行(一行将包含错误消息,一行将包含日志函数,因为您在函数中创建了错误对象)。

如果您想要更强大的日志记录 - 请使用A proper wrapper for console.log with correct line number?作为@DoXicK建议

答案 4 :(得分:0)

有几种方法可以快速解决这个问题。

1 - 使用console.error   不太方便,实际错误将被忽视,并且在控制台输出中看到大量红色可能会对您的士气产生负面影响。简而言之 - 不要使用,除非它是一个非常小的脚本或一些测试

2 - 将您的日志方法添加到Object的原型中 获得当前的范围/模块名称/等等。更加灵活和优雅。

Object.prototype.log = function(message){
    console.log({
        'message': message,
        'caller': this, 
        'stack':arguments.callee.caller.toString()
    });
};

使用(任何地方):

this.log("foo");

您可以添加this线程中的技术以获取对象内的确切函数名称,如下所示:

    var callerFunc = arguments.callee.caller.toString();
    callerFuncName = (callerFunc.substring(callerFunc.indexOf("function") + 9, callerFunc.indexOf("(")) || "anoynmous");

然而,确保你的范围被命名......迫使你离开:

Module.method = function(){}

对此:

Module.method = function method(){}

至于行号,调用(new Error())将允许您访问调用它的行号 - 甚至不在所有浏览器上。

创建优雅的调试功能是一项工作

尽管我不愿意承认,另一个暗示reg-exps尝试结果的答案似乎是更快地解决你的问题。

答案 5 :(得分:0)

我在Node中使用了它,它特别有效。 Console.log只是一个函数,可以安全地保存和重新分配它,并在完成后返回。我没有理由相信这在浏览器中也不起作用。

//Store console.log function in an object so
//we can still use it.
theConsole = {};
theConsole.log = console.log;

//This function is called when console.log occurs
//arguments[0] is what would normally be printed.
console.log = function(){
    theConsole.log(">" + arguments[0]);
}

//Call our console.log wrapper
console.log("Testing testing 123");
console.log("Check one two");

//Put back the way it was
console.log = theConsole.log;
console.log("Now normal");

答案 6 :(得分:-1)

似乎你们所有人都在努力挣扎。我有一个简单的单线解决方案:-

//Just do this, that I have done below: HAVE FUN

var log=console.log;

log(`So this way is known as Aniket's way.`);
log(`Don't be too serious this is just the fun way of doing same thing`);

log(`Thank You`)

相关问题