[javascript] 예외를 던질 때 JavaScript 스택 추적을 어떻게 얻을 수 있습니까?

JavaScript 예외를 직접 발생시키는 경우 (예 throw "AArrggg"🙂 스택 추적을 얻는 방법 (Firebug 또는 기타) 바로 지금 메시지를 받았습니다.

편집 : 아래 많은 사람들이 게시 한 것처럼, 그것은을위한 스택 추적을 얻을 수 있습니다 자바 스크립트 예외를 하지만 난에 대한 스택 추적을 얻고 싶은 예외. 예를 들면 다음과 같습니다.

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);
}


답변

크롬 / 크롬 (V8을 사용하는 다른 브라우저)과 Firefox는 Error 객체 의 스택 속성을 통해 스택 추적을 얻을 수있는 편리한 인터페이스를 제공 합니다.

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

그것은 당신이 던지는 예외뿐만 아니라 기본 예외에도 적용됩니다. (어쨌든 모범 사례 인 Error 클래스를 사용하는 것으로 간주됩니다).

V8 문서에 대한 세부 사항 참조


답변

Firefox에서는 예외를 던질 필요가없는 것 같습니다. 충분하다

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


답변

방화범이 있으면 스크립트 탭에 모든 오류에 대한 휴식 옵션이 있습니다. 스크립트가 중단 점에 도달하면 Firebug의 스택 창을 볼 수 있습니다.

스크린 샷


답변

원래 질문에 대한 의견에서 지적한 바와 같이 좋은 (그리고 간단한) 해결책 stackError객체 의 속성을 다음과 같이 사용하는 것입니다.

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.js

Console개체 의 설정을 가지고 놀아 보십시오! 트레이스 라인 사이에 간격을 추가하고 완전히 끌 수 있습니다. 여기에 Console.trace설정되어 있습니다 false:

흔적 없음

당신도 같이 정보의 첫 번째 비트 (설정 해제 할 수 있습니다 Console.settings.debug.showInfofalse) 또는 완전히 비활성화 디버깅 (설정 Console.settings.debug.enabled에를 false다시 디버그 문을 주석 필요가 없습니다 그래서)! 그것들을 그대로두면 아무것도하지 않습니다.


답변

나는 당신이 사용할 수있는 내장 된 것이 없다고 생각하지만, 사람들이 자신을 굴리는 많은 예를 찾았습니다.


답변

인스턴스를 던지더라도 인스턴스 의 stack( stacktraceOpera에서) 속성에 액세스 할 수 있습니다 Error. 문제는 반드시 사용해야합니다 throw new Error(string)( 대신 새로운 것을 잊지 마십시오 ) throw string.

예:

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