如果我自己抛出一个JavaScript异常(例如,抛出“AArrggg”),我如何获得堆栈跟踪(在Firebug或其他)?现在我刚收到消息。

编辑:正如下面许多人发布的那样,可以为JavaScript异常获得堆栈跟踪,但我想为我的异常获得堆栈跟踪。例如:

function foo() {
    bar(2);
}
function bar(n) {
    if (n < 2)
        throw "Oh no! 'n' is too small!"
    bar(n-1);
}

当调用foo时,我想获得一个堆栈跟踪,其中包括对foo, bar, bar的调用。


当前回答

哇——我在6年里没有看到一个人建议我们在使用堆栈之前先检查它是否可用!在错误处理程序中,最糟糕的事情就是因为调用了不存在的东西而抛出错误。

正如其他人所说,虽然stack现在使用起来很安全,但在IE9或更早的版本中不受支持。

我记录我的意外错误和堆栈跟踪是相当必要的。为了获得最大的支持,我首先检查Error.prototype.stack是否存在并且是一个函数。如果是,那么使用error.stack是安全的。

        window.onerror = function (message: string, filename?: string, line?: number, 
                                   col?: number, error?: Error)
        {
            // always wrap error handling in a try catch
            try 
            {
                // get the stack trace, and if not supported make our own the best we can
                var msg = (typeof Error.prototype.stack == 'function') ? error.stack : 
                          "NO-STACK " + filename + ' ' + line + ':' + col + ' + message;

                // log errors here or whatever you're planning on doing
                alert(msg);
            }
            catch (err)
            {

            }
        };

编辑:似乎因为堆栈是一个属性而不是一个方法,你可以安全地调用它,即使在旧的浏览器。我仍然感到困惑,因为我非常确定检查错误。原型以前为我工作,现在它不-所以我不确定发生了什么。

其他回答

在Firefox中,似乎不需要抛出异常。这就足够了

e = new Error();
console.log(e.stack);

有点晚了,但是,这里有另一个解决方案,它自动检测if参数。callee可用,并使用new Error()。如果没有,就堆叠。 在chrome, safari和firefox测试。

2个变体——stackFN(n)给出了离直接调用方n远的函数名,stackArray()给出了一个数组,stackArray()[0]是直接调用方。

在http://jsfiddle.net/qcP9y/6/上试试吧

// returns the name of the function at caller-N
// stackFN()  = the immediate caller to stackFN
// stackFN(0) = the immediate caller to stackFN
// stackFN(1) = the caller to stackFN's caller
// stackFN(2) = and so on
// eg console.log(stackFN(),JSON.stringify(arguments),"called by",stackFN(1),"returns",retval);
function stackFN(n) {
    var r = n ? n : 0, f = arguments.callee,avail=typeof f === "function",
        s2,s = avail ? false : new Error().stack;
    if (s) {
        var tl=function(x) { s = s.substr(s.indexOf(x) + x.length);},
        tr = function (x) {s = s.substr(0, s.indexOf(x) - x.length);};
        while (r-- >= 0) {
            tl(")");
        }
        tl(" at ");
        tr("(");
        return s;
    } else {
        if (!avail) return null;
        s = "f = arguments.callee"
        while (r>=0) {
            s+=".caller";
            r--;   
        }
        eval(s);
        return f.toString().split("(")[0].trim().split(" ")[1];
    }
}
// same as stackFN() but returns an array so you can work iterate or whatever.
function stackArray() {
    var res=[],f = arguments.callee,avail=typeof f === "function",
        s2,s = avail ? false : new Error().stack;
    if (s) {
        var tl=function(x) { s = s.substr(s.indexOf(x) + x.length);},
        tr = function (x) {s = s.substr(0, s.indexOf(x) - x.length);};
        while (s.indexOf(")")>=0) {
            tl(")");
            s2= ""+s;
            tl(" at ");
            tr("(");
            res.push(s);
            s=""+s2;
        }
    } else {
        if (!avail) return null;
        s = "f = arguments.callee.caller"
        eval(s);
        while (f) {
            res.push(f.toString().split("(")[0].trim().split(" ")[1]);
            s+=".caller";
            eval(s);
        }
    }
    return res;
}


function apple_makes_stuff() {
    var retval = "iPhones";
    var stk = stackArray();

    console.log("function ",stk[0]+"() was called by",stk[1]+"()");
    console.log(stk);
    console.log(stackFN(),JSON.stringify(arguments),"called by",stackFN(1),"returns",retval);
    return retval;
}



function apple_makes (){
    return apple_makes_stuff("really nice stuff");
}

function apple () {
    return apple_makes();
}

   apple();

这里有一个答案,给你最大的性能(IE 6+)和最大的兼容性。兼容IE 6!

function stacktrace( log_result ) { var trace_result; // IE 6 through 9 compatibility // this is NOT an all-around solution because // the callee property of arguments is depredicated /*@cc_on // theese fancy conditinals make this code only run in IE trace_result = (function st2(fTmp) { // credit to Eugene for this part of the code return !fTmp ? [] : st2(fTmp.caller).concat([fTmp.toString().split('(')[0].substring(9) + '(' + fTmp.arguments.join(',') + ')']); })(arguments.callee.caller); if (log_result) // the ancient way to log to the console Debug.write( trace_result ); return trace_result; @*/ console = console || Console; // just in case if (!(console && console.trace) || !log_result){ // for better performance in IE 10 var STerror=new Error(); var unformated=(STerror.stack || STerror.stacktrace); trace_result = "\u25BC console.trace" + unformated.substring(unformated.indexOf('\n',unformated.indexOf('\n'))); } else { // IE 11+ and everyone else compatibility trace_result = console.trace(); } if (log_result) console.log( trace_result ); return trace_result; } // test code (function testfunc(){ document.write( "<pre>" + stacktrace( false ) + "</pre>" ); })();

对Eugene的回答进行了更新:为了让IE(特定版本?)填充堆栈属性,必须抛出错误对象。下面的例子应该比他现在的例子工作得更好,并且应该避免在IE中返回undefined。

function stackTrace() {
  try {
    var err = new Error();
    throw err;
  } catch (err) {
    return err.stack;
  }
}

注1:这类事情只应该在调试时执行,在运行时禁用,特别是频繁调用时。注2:这可能不能在所有浏览器中工作,但似乎可以在FF和IE 11中工作,这很适合我的需求。

试试

throw new Error('some error here')

这对铬来说非常有效: