当我抛出一个exception时,如何获得一个Javascript堆栈跟踪?

如果我自己抛出一个Javascriptexception(例如throw "AArrggg" ),我怎么能得到堆栈跟踪(在Firebug或其他)? 现在我只是得到消息。

编辑 :由于许多人下面已经发布,有可能得到一个JavaScriptexception的堆栈跟踪,但我想获得一个堆栈跟踪我的例外。 例如:

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

foo被调用的时候,我想得到一个包含对foobarbar的调用的栈跟踪。

这段代码的修改版本可能会有所帮助:

 function stacktrace() { function st2(f) { return !f ? [] : st2(f.caller).concat([f.toString().split('(')[0].substring(9) + '(' + f.arguments.join(',') + ')']); } return st2(arguments.callee.caller); } 

编辑(2017):

在所有现代浏览器中,您只需调用: console.trace(); (MDN参考)

编辑:

在原始问题的注释中指出的更好(更简单)的解决scheme是使用Error对象的stack属性,如下所示:

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

这将产生这样的输出:

 DBX.Utils.stackTrace@http://localhost:49573/assets/js/scripts.js:44 DBX.Console.Debug@http://localhost:49573/assets/js/scripts.js:9 .success@http://localhost:49573/:462 x.Callbacks/c@http://localhost:49573/assets/js/jquery-1.10.2.min.js:4 x.Callbacks/p.fireWith@http://localhost:49573/assets/js/jquery-1.10.2.min.js:4 k@http://localhost:49573/assets/js/jquery-1.10.2.min.js:6 .send/r@http://localhost:49573/assets/js/jquery-1.10.2.min.js:6 

给出调用函数的名称以及URL,调用函数等等。

请注意,铬/铬(其他浏览器使用V8)确实有一个方便的接口,通过错误对象上的堆栈属性获取堆栈跟踪。

 try { // Code throwing an exception } catch(e) { console.log(e.stack); } 

它适用于基本的例外,也适用于你自己抛出的例外。 (考虑到你使用了Error类,这是一个很好的习惯)。

查看V8文档的详细信息

在Firefox中,似乎你不需要抛出exception。 这是足够的

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

如果您有萤火虫,脚本选项卡中的所有错误选项都会中断。 一旦脚本已经达到你的断点,你可以看看萤火虫的堆栈窗口:

截图

我不认为有什么可以使用的东西,但是我find了很多自己滚动的例子。

  • DIY的javascript堆栈跟踪
  • 任何浏览器的Javascript堆栈跟踪

在原始问题的注释中指出的一个好的(和简单的)解决scheme是使用Error对象的stack属性,如下所示:

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

这将产生这样的输出:

 DBX.Utils.stackTrace@http://localhost:49573/assets/js/scripts.js:44 DBX.Console.Debug@http://localhost:49573/assets/js/scripts.js:9 .success@http://localhost:49573/:462 x.Callbacks/c@http://localhost:49573/assets/js/jquery-1.10.2.min.js:4 x.Callbacks/p.fireWith@http://localhost:49573/assets/js/jquery-1.10.2.min.js:4 k@http://localhost:49573/assets/js/jquery-1.10.2.min.js:6 .send/r@http://localhost:49573/assets/js/jquery-1.10.2.min.js:6 

给出调用函数的名称以及URL和行号,调用函数等等。

我有一个非常精巧和漂亮的解决scheme,我为当前正在开发的一个项目devise了一个项目,并且已经提取并重新编写了一些项目以进行概括。 这里是:

 (function(context){ // Only global namespace. var Console = { //Settings settings: { debug: { alwaysShowURL: false, enabled: true, showInfo: true }, stackTrace: { enabled: true, collapsed: true, ignoreDebugFuncs: true, spacing: false } } }; // String formatting prototype function. if (!String.prototype.format) { String.prototype.format = function () { var s = this.toString(), args = typeof arguments[0], args = (("string" == args || "number" == args) ? arguments : arguments[0]); if (!arguments.length) return s; for (arg in args) s = s.replace(RegExp("\\{" + arg + "\\}", "gi"), args[arg]); return s; } } // String repeating prototype function. if (!String.prototype.times) { String.prototype.times = function () { var s = this.toString(), tempStr = "", times = arguments[0]; if (!arguments.length) return s; for (var i = 0; i < times; i++) tempStr += s; return tempStr; } } // Commonly used functions Console.debug = function () { if (Console.settings.debug.enabled) { var args = ((typeof arguments !== 'undefined') ? Array.prototype.slice.call(arguments, 0) : []), sUA = navigator.userAgent, currentBrowser = { firefox: /firefox/gi.test(sUA), webkit: /webkit/gi.test(sUA), }, aLines = Console.stackTrace().split("\n"), aCurrentLine, iCurrIndex = ((currentBrowser.webkit) ? 3 : 2), sCssBlack = "color:black;", sCssFormat = "color:{0}; font-weight:bold;", sLines = ""; if (currentBrowser.firefox) aCurrentLine = aLines[iCurrIndex].replace(/(.*):/, "$1@").split("@"); else if (currentBrowser.webkit) aCurrentLine = aLines[iCurrIndex].replace("at ", "").replace(")", "").replace(/( \()/gi, "@").replace(/(.*):(\d*):(\d*)/, "$1@$2@$3").split("@"); // Show info if the setting is true and there's no extra trace (would be kind of pointless). if (Console.settings.debug.showInfo && !Console.settings.stackTrace.enabled) { var sFunc = aCurrentLine[0].trim(), sURL = aCurrentLine[1].trim(), sURL = ((!Console.settings.debug.alwaysShowURL && context.location.href == sURL) ? "this page" : sURL), sLine = aCurrentLine[2].trim(), sCol; if (currentBrowser.webkit) sCol = aCurrentLine[3].trim(); console.info("%cOn line %c{0}%c{1}%c{2}%c of %c{3}%c inside the %c{4}%c function:".format(sLine, ((currentBrowser.webkit) ? ", column " : ""), ((currentBrowser.webkit) ? sCol : ""), sURL, sFunc), sCssBlack, sCssFormat.format("red"), sCssBlack, sCssFormat.format("purple"), sCssBlack, sCssFormat.format("green"), sCssBlack, sCssFormat.format("blue"), sCssBlack); } // If the setting permits, get rid of the two obvious debug functions (Console.debug and Console.stackTrace). if (Console.settings.stackTrace.ignoreDebugFuncs) { // In WebKit (Chrome at least), there's an extra line at the top that says "Error" so adjust for this. if (currentBrowser.webkit) aLines.shift(); aLines.shift(); aLines.shift(); } sLines = aLines.join(((Console.settings.stackTrace.spacing) ? "\n\n" : "\n")).trim(); trace = typeof trace !== 'undefined' ? trace : true; if (typeof console !== "undefined") { for (var arg in args) console.debug(args[arg]); if (Console.settings.stackTrace.enabled) { var sCss = "color:red; font-weight: bold;", sTitle = "%c Stack Trace" + " ".times(70); if (Console.settings.stackTrace.collapsed) console.groupCollapsed(sTitle, sCss); else console.group(sTitle, sCss); console.debug("%c" + sLines, "color: #666666; font-style: italic;"); console.groupEnd(); } } } } Console.stackTrace = function () { var err = new Error(); return err.stack; } context.Console = Console; })(window); 

看看GitHub (目前v1.2)! 你可以使用它像Console.debug("Whatever"); 它将根据Console的设置,打印输出和堆栈跟踪(或简单的信息/没有额外的东西)。 这是一个例子:

Console.js

确保使用Console对象中的设置! 您可以在轨迹线之间添加间距,并将其完全closures。 这里把Console.trace设置为false

没有痕迹

您甚至可以closures显示的第一个信息(将Console.settings.debug.showInfo设置为false )或者完全禁用debugging(将Console.settings.debug.enabled设置为false ),以便您不必再次注释debugging语句! 只要让他们进入,这将无能为力。

即使您抛出它,也可以访问Error实例的stack (Opera的stack stacktrace )属性。 事情是,你需要确保你使用throw new Error(string) (不要忘记新的,而不是throw string

例:

 try { 0++; } catch (e) { var myStackTrace = e.stack || e.stacktrace || ""; } 

在Firebug上获得真实堆栈跟踪的一种方法是创build一个真正的错误,如调用一个未定义的函数:

 function foo(b){ if (typeof b !== 'string'){ // undefined Error type to get the call stack throw new ChuckNorrisError("Chuck Norris catches you."); } } function bar(a){ foo(a); } foo(123); 

或者使用console.error()后跟一个throw语句,因为console.error()显示堆栈跟踪。

使用Chrome浏览器,您可以使用console.trace方法: https : //developer.chrome.com/devtools/docs/console-api#consoletraceobject

Eugene的答案更新:为了使IE(特定版本?)能够填充stack属性,必须抛出错误对象。 以下应该比他当前的例子更好地工作,并应避免在IE中返回undefined

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

注1:这种事情应该只在debugging时才能完成,而在生存时禁用,尤其是在经常调用的情况下。 注2:这可能不适用于所有的浏览器,但似乎在FF和IE 11,这适合我的需要就好了。

这将为现代的Chrome,Opera,Firefox和IE10 +提供堆栈跟踪(作为string数组)

 function getStackTrace () { var stack; try { throw new Error(''); } catch (error) { stack = error.stack || ''; } stack = stack.split('\n').map(function (line) { return line.trim(); }); return stack.splice(stack[0] == 'Error' ? 2 : 1); } 

用法:

 console.log(getStackTrace().join('\n')); 

它从堆栈中排除了自己的调用,以及Chrome和Firefox(不包括IE)使用的标题“错误”。

它不应该在旧的浏览器崩溃,但只是返回空数组。 如果你需要更多的通用解决scheme,请看stacktrace.js 。 它支持的浏览器列表真的很让人印象深刻,但在我看来,这是一个很小的任务,它的目标是:37Kb的缩小文本,包括所有的依赖关系。

在谷歌浏览器(版本19.0及更高版本)中,简单地抛出一个exception是完美的。 例如:

 /* file: code.js, line numbers shown */ 188: function fa() { 189: console.log('executing fa...'); 190: fb(); 191: } 192: 193: function fb() { 194: console.log('executing fb...'); 195: fc() 196: } 197: 198: function fc() { 199: console.log('executing fc...'); 200: throw 'error in fc...' 201: } 202: 203: fa(); 

将在浏览器的控制台输出中显示堆栈跟踪:

 executing fa... code.js:189 executing fb... code.js:194 executing fc... cdoe.js:199 /* this is your stack trace */ Uncaught error in fc... code.js:200 fc code.js:200 fb code.js:195 fa code.js:190 (anonymous function) code.js:203 

希望这个帮助。

 <script type="text/javascript" src="https://rawgithub.com/stacktracejs/stacktrace.js/master/stacktrace.js"></script> <script type="text/javascript"> try { // error producing code } catch(e) { var trace = printStackTrace({e: e}); alert('Error!\n' + 'Message: ' + e.message + '\nStack trace:\n' + trace.join('\n')); // do something else with error } </script> 

这个脚本会显示错误

function:

 function print_call_stack(err) { var stack = err.stack; console.error(stack); } 

用例:

  try{ aaa.bbb;//error throw here } catch (err){ print_call_stack(err); } 

你可以使用这个库http://www.stacktracejs.com/ 。 这很好

从文档

您也可以通过自己的错误来获得堆栈跟踪不可用在IE或Safari 5-

 <script type="text/javascript" src="https://rawgithub.com/stacktracejs/stacktrace.js/master/stacktrace.js"></script> <script type="text/javascript"> try { // error producing code } catch(e) { var trace = printStackTrace({e: e}); alert('Error!\n' + 'Message: ' + e.message + '\nStack trace:\n' + trace.join('\n')); // do something else with error } </script> 

这个在现代(2017)浏览器(IE11,Opera,Chrome,FireFox,Yandex)中使用的polyfill代码:

 printStackTrace: function () { var err = new Error(); var stack = err.stack || /*old opera*/ err.stacktrace || ( /*IE11*/ console.trace ? console.trace() : "no stack info"); return stack; } 

其他答案:

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

不在IE 11中工作!

使用arguments.callee.caller – 在任何浏览器中都不能在严格模式下工作!

在Firefox上获取堆栈跟踪比在IE上更容易,但基本上这是你想要做的:

将“有问题的”代码包装在try / catch块中:

 try { // some code that doesn't work var t = null; var n = t.not_a_value; } catch(e) { } 

如果您将检查“错误”对象的内容,它包含以下字段:

e.fileName:问题来自e.lineNumber的源文件/页面:出现问题的文件/页面中的行号e.message:描述发生什么types错误的简单消息e.name:types发生错误,在上面的例子中应该是'TypeError'e.stack:包含导致exception的堆栈跟踪

我希望这可以帮助你。

那种晚了,但是,这里是另一种解决scheme,如果arguments.callee可用,它会自动检测,如果不是,则使用新的Error()。 testing铬,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(); 

我不得不调查与IE11 smartgwt无限recursion,所以为了深入调查,我需要一个堆栈跟踪。 问题是,我无法使用开发控制台,因为复制更困难的方式。
在javascript方法中使用以下内容:

 try{ null.toString(); } catch(e) { alert(e.stack); } 

哇 – 我6年没有见到一个人,build议我们在使用前先检查stack是否可用! 在error handling程序中可以做的最糟糕的事情是抛出一个错误,因为调用了一些不存在的东西。

正如其他人所说,虽然stack现在大多是安全的,但在IE9或更早版本中不支持。

我logging我的意外错误和堆栈跟踪是非常重要的。 为了获得最大支持,我首先检查是否存在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) { } }; 

编辑:看来,由于stack是一个属性,而不是一个方法,你可以安全地调用它,即使在旧的浏览器。 我仍然困惑,因为我非常确定检查Error.prototype以前为我工作,现在它不 – 所以我不知道发生了什么事情。

使用console.error(e.stack) Firefox只显示日志中的console.error(e.stack) ,Chrome也显示消息。 如果消息包含重要信息,这可能是一个不好的惊喜。 始终logging两者。

 function stacktrace(){ return (new Error()).stack.split('\n').reverse().slice(0,-2).reverse().join('\n'); } 

这是一个答案,给你最大的性能(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>" ); })(); 

你试一试

 throw new Error('some error here') 

这对于Chrome来说非常适用:

在这里输入图像描述