如果我自己抛出JavaScript异常(例如,throw "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
的调用。
答案 0 :(得分:643)
编辑2(2017):
在所有现代浏览器中,您只需致电:console.trace();
(MDN Reference)
编辑1(2013):
原始问题的评论中指出的更好(更简单)的解决方案是使用stack
对象的Error
属性,如下所示:
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,调用函数等。
原创(2009年):
this snippet的修改版本可能会有所帮助:
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);
}
答案 1 :(得分:170)
请注意,chrome / chrome(使用V8的其他浏览器)以及Firefox确实有一个方便的界面来通过错误对象上的堆栈属性获取堆栈跟踪。< / p>
try {
// Code throwing an exception
} catch(e) {
console.log(e.stack);
}
它适用于基本异常以及您自己抛出的异常。 (认为您使用的是Error类,这无论如何都是一种很好的做法)。
答案 2 :(得分:76)
在Firefox中,您似乎不需要抛出异常。
就足够了e = new Error();
console.log(e.stack);
答案 3 :(得分:25)
如果您有firebug,则脚本选项卡中的所有错误选项都会中断。一旦脚本达到你的断点,你就可以看一下firebug的堆栈窗口:
答案 4 :(得分:10)
原始问题的评论中指出的一个好的(简单的)解决方案是使用stack
对象的Error
属性,如下所示:
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和行号,调用函数等。
我有一个非常精细和漂亮的解决方案,我已经为我正在进行的项目设计了这个解决方案,我已经提取并重新设计了一些以便进行推广。这是:
(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
对象中的设置!您可以在轨迹线之间添加间距并将其完全关闭。这是Console.trace
设置为false
:
您甚至可以关闭显示的第一位信息(将Console.settings.debug.showInfo
设置为false
)或完全禁用调试(将Console.settings.debug.enabled
设置为false
),这样您就永远不会再次注释掉调试语句!只要让他们进去,这将无济于事。
答案 5 :(得分:10)
我不认为你可以使用任何内置的东西,但我确实找到了很多人自己动手的例子。
答案 6 :(得分:7)
您可以访问stack
实例的stacktrace
(Opera中的Error
)属性,即使您扔了它也是如此。问题是,您需要确保使用throw new Error(string)
(不要忘记新而不是throw string
。
示例:
try {
0++;
} catch (e) {
var myStackTrace = e.stack || e.stacktrace || "";
}
答案 7 :(得分:7)
使用Chrome浏览器,您可以使用console.trace
方法:https://developer.chrome.com/devtools/docs/console-api#consoletraceobject
答案 8 :(得分:6)
在Firebug上获得真正的堆栈跟踪的一种方法是创建一个真正的错误,比如调用一个未定义的函数:
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()
显示了堆栈跟踪。
答案 9 :(得分:6)
这将为现代Chrome,Opera,Firefox和IE10 +提供堆栈跟踪(作为字符串数组)
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)使用的标题“错误”。
它不应该在旧浏览器上崩溃,而只是返回空数组。如果您需要更通用的解决方案,请查看stacktrace.js。它支持的浏览器列表确实令人印象深刻,但在我看来,这对于它的小任务非常重要:37Kb的缩小文本,包括所有依赖项。
答案 10 :(得分:6)
Eugene答案的更新:必须抛出错误对象,IE(特定版本?)才能填充stack
属性。以下应该比他当前的示例更好,并且应该避免在IE中返回undefined
。
function stackTrace() {
try {
var err = new Error();
throw err;
} catch (err) {
return err.stack;
}
}
注1:此类事情只应在调试时完成,并在实时时禁用,特别是在频繁调用时。注2:这可能不适用于所有浏览器,但似乎适用于FF和IE 11,这很适合我的需要。
答案 11 :(得分:3)
在谷歌浏览器(版本19.0及更高版本)中,简单地抛出异常非常有效。例如:
/* 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
希望得到这个帮助。
答案 12 :(得分:2)
此填充代码适用于现代(2017)浏览器(IE11,Opera,Chrome,FireFox,Yandex):
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 - 在任何浏览器中都不能在严格模式下工作!
答案 13 :(得分:2)
功能:
function print_call_stack(err) {
var stack = err.stack;
console.error(stack);
}
用例:
try{
aaa.bbb;//error throw here
}
catch (err){
print_call_stack(err);
}
答案 14 :(得分:2)
<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>
此脚本将显示错误
答案 15 :(得分:1)
至少在 Edge 2021 中:
console.groupCollapsed('jjjjjjjjjjjjjjjjj')
console.trace()
try {
throw "kuku"
} catch(e) {
console.log(e.stack)
}
console.groupEnd()
traceUntillMe()
你已经完成了我的朋友
答案 16 :(得分:1)
这是一个给您最大性能(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>" );
})();
&#13;
答案 17 :(得分:1)
function stacktrace(){
return (new Error()).stack.split('\n').reverse().slice(0,-2).reverse().join('\n');
}
答案 18 :(得分:1)
您可以使用此库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>
答案 19 :(得分:1)
派对迟到了,但是,这是另一种解决方案,如果arguments.callee可用,则自动检测,如果没有,则使用新的Error()。stack。 测试过chrome,safari和firefox。
2个变体 - stackFN(n)为您提供远离直接调用者的函数n的名称,stackArray()为您提供一个数组,stackArray()[0]作为直接调用者。
处试试// 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();
答案 20 :(得分:0)
使用console.error(e.stack)
Firefox仅显示日志中的堆栈跟踪,
Chrome也会显示该消息。
如果消息包含重要信息,这可能是一个不好的惊喜。始终记录两者。
答案 21 :(得分:0)
哇 - 我在6年内没有看到一个人建议我们先使用它来检查stack
是否可用!你可以在错误处理程序中做的最糟糕的事情是抛出一个错误,因为调用了一些不存在的东西。
正如其他人所说,虽然现在使用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)
{
}
};
修改:由于stack
是一个属性而不是一种方法,因此即使在较旧的浏览器上也可以安全地调用它。我仍然感到困惑,因为我非常确定先前检查Error.prototype
对我有效,现在它没有 - 所以我不确定发生了什么。
答案 22 :(得分:0)
我不得不用IE11调查smartgwt中的无限递归,所以为了更深入地研究,我需要一个堆栈跟踪。问题是,我无法使用开发控制台,因为这种复制更加困难 在javascript方法中使用以下内容:
try{ null.toString(); } catch(e) { alert(e.stack); }
答案 23 :(得分:0)
答案 24 :(得分:0)
在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:描述发生了什么类型错误的简单消息 e.name:发生的错误类型,在上面的示例中应该是'TypeError' e.stack:包含导致异常的堆栈跟踪
我希望这可以帮助你。