自分自身でJavaScriptの例外(例えばthrow "AArrggg"
)を投げた場合、どうやったら(Firebugあるいはそれ以外で)スタックトレースを取得できますか?今私はメッセージを受け取るだけです。
edit :以下の多くの人が投稿したように、 JavaScript例外 のスタックトレースを取得することは可能ですが、 my 例外のスタックトレースを取得したいです。例えば:
function foo() {
bar(2);
}
function bar(n) {
if (n < 2)
throw "Oh no! 'n' is too small!"
bar(n-1);
}
foo
が呼び出されたとき、私はfoo
、bar
、bar
への呼び出しを含むスタックトレースを取得したいと思います。
編集2(2017):
最近のブラウザでは、単に以下のように呼び出すことができます。console.trace();
(MDNリファレンス)
編集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):
このスニペット の修正版は、いくらか役立つかもしれません:
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);
}
Chrom/chrome(V8を使用している他のブラウザ)やFirefoxには、 stack プロパティの Error オブジェクトを通じてスタックトレースを取得するための便利なインターフェースがあります。
try {
// Code throwing an exception
} catch(e) {
console.log(e.stack);
}
それはあなたが自分自身を投げるものと同様に基本的な例外に適用されます。 (Errorクラスを使用することを検討してください。とにかく良い習慣です)。
Firefoxでは、例外をスローする必要はないようです。それで十分です
e = new Error();
console.log(e.stack);
あなたがFirebugを持っているなら、スクリプトタブのすべてのエラーオプションにブレークがあります。スクリプトがブレークポイントに達すると、firebugのスタックウィンドウを見ることができます。
私はあなたが使うことができるものが何も内蔵されているとは思わないが、私は彼ら自身を転がしている人々の例をたくさん見つけた。
元の質問に対するコメントで指摘されているような良い(そして単純な)解決策は、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
に設定)することもできます。それらをそのままにしておくと、これは何もしません。
stack
インスタンスのstacktrace
(OperaではError
)プロパティに投げたとしてもアクセスすることができます。問題は、throw new Error(string)
を必ず使用するようにする必要があることです(throw string
の代わりに new を忘れないでください)。
例:
try {
0++;
} catch (e) {
var myStackTrace = e.stack || e.stacktrace || "";
}
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:この種のことはデバッグ時にのみ行われ、ライブ時、特に頻繁に呼び出される場合は無効にされるべきです。注意2:これはすべてのブラウザでうまくいくとは限りませんが、FFとIE 11でうまくいくようですが、これは私のニーズにぴったりです。
firebugで実際のスタックトレースを取得する1つの方法は、未定義の関数を呼び出すような実際のエラーを作成することです。
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()
はスタックトレースを表示するので、console.error()
の後にthrow
ステートメントを続けて使用します。
これにより、現代の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によって使用されるタイトル "Error"を除く(しかしIEは除く)。
古いブラウザではクラッシュしないはずですが、空の配列を返すだけです。もっと普遍的な解決策が必要な場合は stacktrace.js をご覧ください。サポートされているブラウザのリストは非常に印象的ですが、私の心にはそれが意図されているその小さなタスクのために非常に大きいです。
Google Chrome(バージョン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
この助けを願っています。
関数:
function print_call_stack(err) {
var stack = err.stack;
console.error(stack);
}
使用事例:
try{
aaa.bbb;//error throw here
}
catch (err){
print_call_stack(err);
}
<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>
このスクリプトはエラーを表示します
このpolyfillコードは、現代の(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の使用 - どのブラウザでもstrictモードでは動作しません!
パーティーに遅刻するようなものですが、arguments.calleeが利用可能であればを自動検出し、そうでなければnew Error()。stackを使用する別の解決策があります。クロム、サファリ、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();
あなたはこのライブラリを使うことができます http://www.stacktracejs.com/ 。これはとてもいいです
ドキュメンテーションから
あなた自身のErrorを渡して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>
これはあなたに最大のパフォーマンス(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>" );
})();
function stacktrace(){
return (new Error()).stack.split('\n').reverse().slice(0,-2).reverse().join('\n');
}
私はIE11を使ってsmartgwtで無限の再帰を調査しなければならなかったので、もっと深く調査するためにはスタックトレースが必要でした。問題は、私が開発コンソールを使用することができなかったということでした。なぜなら、再現はそのようにもっと難しいからです。
JavaScriptのメソッドでは以下を使用してください。
try{ null.toString(); } catch(e) { alert(e.stack); }
FirefoxではIEよりもスタックトレースを取得する方が簡単ですが、基本的には以下のようにします。
"問題のある"コードをtry/catchブロックで囲みます。
try {
// some code that doesn't work
var t = null;
var n = t.not_a_value;
}
catch(e) {
}
"error"オブジェクトの内容を調べると、次のフィールドがあります。
e.fileName:問題が発生したソースファイル/ページe.lineNumber:問題が発生したファイル/ページ内の行番号e.message:発生したエラーの種類を説明する簡単なメッセージe.name:タイプ発生したエラーの例、上記の例では 'TypeError'とする必要があります。e.stack:例外の原因となったスタックトレースが含まれます。
これがお役に立てば幸いです。
うわー - 私はそれを使う前にstack
が利用可能かどうか私たちが最初にチェックすることを提案している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)
{
}
};
編集: stack
はプロパティでありメソッドではないため、古いブラウザでも安全に呼び出すことができます。私はError.prototype
が以前に私のために働いていたのを確かに確かめていたので今でもそれが働かないのでまだ混乱しています - だから私は何が起こっているのかわからない。
console.error(e.stack)
Firefoxを使用するとログにスタックトレースが表示されるだけで、Chromeはメッセージも表示します。メッセージに重要な情報が含まれている場合、これは驚くことではありません。常に両方を記録してください。