JavaScript 호출자 함수 줄 번호를 얻는 방법은 무엇입니까? JavaScript 호출자 소스 URL을 얻는 방법은 무엇입니까?


109

JavaScript 호출자 함수 이름을 얻기 위해 다음을 사용하고 있습니다.

var callerFunc = arguments.callee.caller.toString();
callerFuncName = (callerFunc.substring(callerFunc.indexOf("function") + 8, callerFunc.indexOf("(")) || "anoynmous")

메서드가 호출 된 줄 번호를 찾는 방법이 있습니까?

또한 메서드가 호출 된 JavaScript 파일의 이름을 가져 오는 방법이 있습니까? 아니면 소스 URL?


2
IE에서는 이것이 가능하지 않다고 생각합니다. 그렇지 않으면 세부 정보를 제공하지 않는 CRAPPY 오류 메시지를 해결할 수있는 방법이 있습니다. 하지만 가능하다면 저도 알고 싶어요!
Zoidberg

예. 다음은 각 브라우저의 고유 한 방법을 사용하는 브라우저 간 기능입니다. github.com/eriwen/javascript-stacktrace [고정 링크]
scotts

답변:


99

이것은 크롬 / QtWebView에서 나를 위해 작동합니다.

function getErrorObject(){
    try { throw Error('') } catch(err) { return err; }
}

var err = getErrorObject();
var caller_line = err.stack.split("\n")[4];
var index = caller_line.indexOf("at ");
var clean = caller_line.slice(index+2, caller_line.length);

노드에서도 작동합니다. 사용자 정의 log () 함수 (예 : Chrome 배열 로깅에 대해 수정 된 다른 유용한 해결 방법을 추가 함)와 log ()를 호출 한 위치에서 줄 번호를 계속 입력합니다.
mikemaccana apr

60
오류를 던질 필요가 없습니다. 간단하게 생성하면 충분합니다.var caller_line = (new Error).stack.split("\n")[4]
ELLIOTTCABLE

2
이 제안을 다른 유사한 답변과 병합하여 FF / Webkit "표준화 된"응답을
얻었습니다.

1
PhantomJS에서도 작동하지만 던져야합니다. 그렇지 않으면 "stack"속성이 오류에 설정되지 않습니다.
Joshua Richardson

1
@ELLIOTTCABLE 실제로 iOS safari와 같은 일부 브라우저에서는 예외를 throw해야합니다! 그럼 왜하지 않습니까?
arctelix

26

kangax의 솔루션은 불필요한 try..catch 범위를 도입합니다. JavaScript에서 행 번호에 액세스해야하는 경우 (Firefox 또는 Opera를 사용하는 한) (new Error).lineNumber.


11
안녕하세요, 애드온에 감사드립니다. 이전 통화에서 회선 번호를 얻을 수 있는지 알고 있습니까? 방법 A가 B를 호출하고 이제 BI에서 A 아래의 어떤 줄에서 호출이 이루어 졌는지 알고 싶습니다.
Tal

85
이것은 선택되었지만 호출자 함수 의 줄 번호를 얻는 방법에 대한 질문에 대답하지 않습니다 .
mikemaccana

3
또한 이것은 매우 제한적입니다. 가장 좋은 해결책은 오류를 던지고 모든 최신 브라우저에서 사용할 수있는 error.stack에 정규식을 사용하는 것입니다. 해당 경로, 파일, 행 및 열을 쉽게 추출 할 수 있습니다. 문제 없어요.
arctelix

13

이 답변의 대부분은 정상적인 경우에도 유용한 디버그 추적을 출력하는 것이 아니라 오류를 처리하기를 원한다고 가정 한 것에 놀랐습니다.

예를 들어 다음과 같은 console.log래퍼를 사용하는 것을 좋아합니다.

consoleLog = function(msg) {//See https://stackoverflow.com/a/27074218/470749
    var e = new Error();
    if (!e.stack)
        try {
            // IE requires the Error to actually be thrown or else the 
            // Error's 'stack' property is undefined.
            throw e;
        } catch (e) {
            if (!e.stack) {
                //return 0; // IE < 10, likely
            }
        }
    var stack = e.stack.toString().split(/\r\n|\n/);
    if (msg === '') {
        msg = '""';
    }
    console.log(msg, '          [' + stack[1] + ']');        
}

그러면 다음과 같은 출력이 콘솔에 인쇄됩니다.

1462567104174 [getAllPosts@http://me.com/helper.js:362:9]

https://stackoverflow.com/a/27074218/올바른 줄 번호가있는 console.log에 대한 적절한 래퍼를 참조 하십시오 .


1
firefox 브라우저에서는 작동하지만 node.js에서는 작동하지 않습니다.
지퍼

1
노드 아래에 스택 [2]을 기록해야합니다
monika mevenkamp

5

이것은 종종 현재 컨텍스트에서 오류를 던져서 달성됩니다. 그런 다음 lineNumberfileName(일부 브라우저에있는) 속성에 대한 오류 개체를 분석합니다.

function getErrorObject(){
  try { throw Error('') } catch(err) { return err; }
}

var err = getErrorObject();

err.fileName;
err.lineNumber; // or `err.line` in WebKit

callee.caller속성이 더 이상 사용되지 않는다는 것을 잊지 마십시오 (처음에는 실제로 ECMA 3rd ed.에는 없었습니다).

또한 함수 디 컴파일은 구현에 따라 달라 지도록 지정되어 있으므로 예상치 못한 결과가 발생할 수 있습니다. 나는 여기여기 에 그것에 대해 썼다 .


감사합니다. 필요한 응용 프로그램에이 코드를 추가하는 것이 약간 문제가있는 것 같습니다. (일부 js 추적 프레임 워크) 사용이 중단되지 않은 다른 방법을 알고 있습니까?
Tal

deprecated에 의존하지 않고 오류 객체를 검사 할 수 있어야합니다 callee.caller.
kangax

오류를 던질 필요가 없습니다. (new Error) .lineNumber를 사용하여 스크립트의 현재 줄 번호에 액세스합니다.
Eli Gray

@Elijah 그것이 내가 FF3에서 보는 것입니다. 반면에 WebKit line은 오류가 발생할 때만 채워집니다 .
kangax

callee.caller의 대체물은 무엇입니까? 함수 이름이 필요한 경우?
Tal

4

내가 좀 늦었 어 :),하지만 토론은 꽤 흥미 롭기 때문에 여기에 간다 ... 오류 핸들러를 만들고 싶다고 가정하고 다음과 같은 예외 핸들러 클래스를 사용하고 있다고 가정한다.

function  errorHandler(error){
    this.errorMessage = error;
}
errorHandler.prototype. displayErrors = function(){
    throw new Error(this.errorMessage);
}

그리고 다음과 같이 코드를 래핑합니다.

try{
if(condition){
    //whatever...
}else{
    throw new errorHandler('Some Error Message');
}
}catch(e){
    e.displayErrors();
}

대부분의 경우 별도의 .js 파일에 오류 처리기가있을 것입니다.

firefox 또는 chrome의 오류 콘솔에서 표시된 코드 줄 번호 (및 파일 이름)는 디버깅을 위해 실제로 원하는 'errorHandler'예외가 아닌 'Error'예외를 발생시키는 줄 (파일)입니다. 쉬운. 자신의 예외를 던지는 것은 좋지만 대규모 프로젝트에서 예외를 찾는 것은 특히 유사한 메시지가있는 경우 상당한 문제가 될 수 있습니다. 따라서 할 수있는 일은 실제 빈 Error 객체에 대한 참조를 오류 처리기에 전달하는 것이며, 해당 참조는 원하는 모든 정보를 보유 할 것입니다 (예를 들어 파이어 폭스에서는 파일 이름과 줄 번호 등을 얻을 수 있습니다.). ; 크롬에서 Error 인스턴스의 'stack'속성을 읽으면 비슷한 것을 얻습니다.) 간단히 말해서 다음과 같이 할 수 있습니다.

function  errorHandler(error, errorInstance){
    this.errorMessage = error;
    this. errorInstance = errorInstance;
}
errorHandler.prototype. displayErrors = function(){
    //add the empty error trace to your message
    this.errorMessage += '  stack trace: '+ this. errorInstance.stack;
    throw new Error(this.errorMessage);
}

try{
if(condition){
    //whatever...
}else{
    throw new errorHandler('Some Error Message', new Error());
}
}catch(e){
    e.displayErrors();
}

이제 사용자 지정 예외를 발생시킨 실제 파일과 줄 번호를 얻을 수 있습니다.


4

줄 번호는 실제로 정적 인 것이므로 로깅을 위해 원하는 경우 gulp와 같은 것으로 전처리 될 수 있습니다. 정확히 그렇게 하는 작은 꿀꺽 꿀꺽 플러그인 을 작성했습니다 .

var gulp = require('gulp');
var logLine = require('gulp-log-line');
gulp.task('log-line', function() {
    return gulp.src("file.js", {buffer : true})
    //Write here the loggers you use.
        .pipe(logLine(['console.log']))
        .pipe(gulp.dest('./build'))

})

gulp.task('default', ['log-line'])

이 CONSOLE.LOG에서 모든 로그에 파일 이름과 라인을 연결되므로 console.log(something)이 될 것이다 console.log('filePath:fileNumber', something). 장점은 이제 파일을 연결하고 트랜스 파일 할 수 있다는 것입니다.


이것은 트랜스 파일러가 사용되는 상황 (예 : TypeScript를 사용할 때)에 대한 훌륭한 제안처럼 보입니다. 감사합니다!
앤디 킹


3

디버깅 목적으로 또는 개발 중에 만 (이유 또는 다른 이유로) 줄 번호를 알고 싶다면 Firebug (Firefox 확장)를 사용하고 예외를 throw 할 수 있습니다 .

편집 :

어떤 이유로 든 프로덕션에서 그렇게해야하는 경우 각 함수가 해당 라인을 추적 할 수 있도록 자바 스크립트 파일을 사전 처리 할 수 ​​있습니다. 코드 범위를 찾는 일부 프레임 워크가 이것을 사용한다는 것을 알고 있습니다 (예 : JSCoverage ).

예를 들어 원래 통화가 다음과 같다고 가정 해 보겠습니다.

function x() {
  1 + 1;
  2 + 2;
  y();
}

전처리기를 작성하여 다음과 같이 만들 수 있습니다.

function x() {
  var me = arguments.callee;
  me.line = 1;
  1 + 1;
  me.line = 2;
  2 + 2;
  me.line = 3;
  y();
}

그런 다음에서를 y()사용 arguments.callee.caller.line하여 다음 과 같이 호출 된 라인을 알 수 있습니다 .

function y() {
  alert(arguments.callee.caller.line);
}

1
감사합니다. 지원상의 이유로 프로덕션에서이 작업을 수행하고 싶습니다. 메서드까지 모든 흐름의 호출 스택을 볼 수있는 코드를 찾았지만 메서드가 호출 된 줄 번호가 없습니다. 나는 그것에 대한 쉬운 해결책을 생각합니까?
Tal

3

이것이 내가 한 방법이며 Firefox와 Chrome에서 테스트했습니다. 이를 통해 함수가 호출 된 위치의 파일 이름과 줄 번호를 확인할 수 있습니다.

logFileAndLineNumber(new Error());

function logFileAndLineNumber(newErr)
{
   if(navigator.userAgent.indexOf("Firefox") != -1)
   {
      var originPath = newErr.stack.split('\n')[0].split("/");
      var fileNameAndLineNumber = originPath[originPath.length - 1].split(">")[0];
      console.log(fileNameAndLineNumber);
   }else if(navigator.userAgent.indexOf("Chrome") != -1)
   {
      var originFile = newErr.stack.split('\n')[1].split('/');
      var fileName = originFile[originFile.length - 1].split(':')[0];
      var lineNumber = originFile[originFile.length - 1].split(':')[1];
      console.log(fileName+" line "+lineNumber);
    }
}

2

이 포럼에서 찾은 정보를 바탕으로 작성한 내용은 다음과 같습니다.

이것은 MyDebugNamespace의 일부이며 Debug는 분명히 예약되어 있으며 네임 스페이스 이름으로 사용되지 않습니다.

    var DEBUG = true;

...

    if (true == DEBUG && !test)
    {
        var sAlert = "Assertion failed! ";
        if (null != message)
            sAlert += "\n" + message;
        if (null != err)
            sAlert += "\n" + "File: " + err.fileName + "\n" + "Line: " + err.lineNumber;
        alert(sAlert);
    }

...

전화하는 방법 :

    MyDebugNamespace.Assert(new Error(""), (null != someVar), "Something is wrong!")

선택적으로 호출에서 메시지 또는 오류를 생략하기 위해 내 네임 스페이스에서이 기본 코드를 호출하는 가변 개수의 인수가있는 두 개의 함수를 포함했습니다.

이것은 Firefox, IE6 및 Chrome에서 잘 작동하며 fileName과 lineNumber를 정의되지 않은 것으로보고합니다.


2

다음 코드는 Mozilla 및 Chrome에서 나를 위해 작동합니다.

파일의 이름과 호출자의 줄을 보여주는 로그 기능.

log: function (arg) {
    var toPrint = [];
    for (var i = 0; i < arguments.length; ++i) {
        toPrint.push(arguments[i]);
    }

    function getErrorObject(){
        try { throw Error('') } catch(err) { return err; }
    }

    var err = getErrorObject(),
        caller;

    if ($.browser.mozilla) {
        caller = err.stack.split("\n")[2];
    } else {
        caller = err.stack.split("\n")[4];
    }

    var index = caller.indexOf('.js');

    var str = caller.substr(0, index + 3);
    index = str.lastIndexOf('/');
    str = str.substr(index + 1, str.length);

    var info = "\t\tFile: " + str;

    if ($.browser.mozilla) {
        str = caller;
    } else {
        index = caller.lastIndexOf(':');
        str = caller.substr(0, index);
    }
    index = str.lastIndexOf(':');
    str = str.substr(index + 1, str.length);
    info += " Line: " + str;
    toPrint.push(info);

    console.log.apply(console, toPrint);
}

뭔가 빠진 것 같습니다. 나는 얻는다 :SyntaxError: function statement requires a name,log: function (arg) {
spiderplant0

이 아이디어가 마음에 들지만 줄 번호가 잘못 나와 있습니다.
Ryan은

2

JavaScript의 사용자 지정 오류에 대한 나의 기여 :

  1. 먼저, 오류 개체 에서 상속에서 @BT 사람과 동의 합니다. 메시지 속성은 어디에 있습니까? , 우리는 그것을 제대로 구축해야합니다 (실제로 여러분은 js 객체 라이브러리를 사용해야합니다. 제가 가장 좋아하는 곳 : https://github.com/jiem/my-class ) :

    window.g3 = window.g3 || {};
    g3.Error = function (message, name, original) {
         this.original = original;
         this.name = name || 'Error.g3';
         this.message = message || 'A g3.Error was thrown!';
         (original)? this.stack = this.original.stack: this.stack = null;
         this.message += '<br>---STACK---<br>' + this.stack;
     };
    
     var ClassEmpty = function() {};
     ClassEmpty.prototype = Error.prototype;
     g3.Error.prototype = new ClassEmpty();
     g3.Error.prototype.constructor = g3.Error;
  2. 그런 다음 전역 오류 처리 함수 (선택 사항)를 정의해야합니다. 그렇지 않으면 엔진이 종료됩니다.

    window.onerror = printError; 
    function printError(msg, url, line){
        document.getElementById('test').innerHTML = msg+'<br>at: '+url+'<br>line: '+line;
        return true;
    }
  3. 마지막으로 사용자 지정 오류를 신중하게 던져야합니다.

    //hit it!
    //throw new g3.Error('Hey, this is an error message!', 'Error.Factory.g3');
    throw new g3.Error('Hey, this is an error message!', 'Error.Factory.g3', new Error());

세 번째 매개 변수를 전달할 때만 new Error()함수와 줄 번호가있는 스택을 볼 수 있습니다!

2에서이 함수는 엔진에서 발생한 오류도 처리 할 수 ​​있습니다.

물론, 진짜 질문은 우리가 정말로 그것을 필요로하는지 언제, 우아한 반환으로 false충분하고 오류가 발생하여 표시 할 중요한 포인트 만 남겨 두는 경우 (제 생각에는 99 %) 가 있습니다.

예 : http://jsfiddle.net/centurianii/m2sQ3/1/


2
console.log(new Error);

전체 트랙을 보여줍니다.


1

어떤 줄이 있는지 확인하려면 특정 관심 줄을 차지하는 코드에 대한 모든 코드를 검색하고 맨 위에서 관심있는이 줄까지 "\ n"문자를 세고 1을 더해야합니다.

나는 실제로 내가 작성하는 응용 프로그램에서이 작업을 수행하고 있습니다. HTML에 대한 모범 사례 유효성 검사기이며 아직 개발 중이지만 관심을 가질만한 오류 출력 프로세스가 완료되었습니다.

http://mailmarkup.org/htmlint/htmlint.html


특정 관심 라인이 여러 개일 수 있습니다. 다른 메서드에서 동일한 메서드를 여러 번 호출 한 경우 호출이 어디에서 왔는지 어떻게 알 수 있습니까 (다른 메서드에서)?
Tal

인터프리터 외부에서 실행시 JavaScript 해석을 분석 할 수 없습니다. 프로그램에서 실행 경로를 추적하는 프로그램을 작성할 수 있지만 분석하려는 코드가 아니라 실행중인 프로그램이됩니다. 이것은 일반적으로 도구를 사용하여 수동으로 수행되는 복잡한 작업입니다. 코드가 실행될 때 코드에서 무슨 일이 일어나고 있는지 정말로보고 싶다면 결정이 어떤 다른 부분을 실행 하는지를 알려주는 메타 데이터를 화면에 쓰도록합니다.

-2

답은 간단합니다. 아니오 및 아니오 (아니오).

자바 스크립트가 소스 파일 / URL의 개념을 실행할 때 쯤이면 소스가 사라졌습니다.

또한 실행시 코드 "줄"이라는 개념이 자바 스크립트에서 더 이상 의미가 없기 때문에 줄 번호를 결정할 방법도 없습니다.

특정 구현은 디버깅 목적으로 이러한 세부 정보에 대한 권한있는 코드 액세스를 허용하는 API 후크를 제공 할 수 있지만 이러한 API는 일반 표준 Javascript 코드에 노출되지 않습니다.


파이어 폭스에서 예외는 그러한 정보를 포함합니다. 적어도 파이어 폭스에서는 가능할까요?
Zoidberg

MS Script 디버거를 시작하고 중단 점을 넣으면 정확히 어디에서 왔는지 호출 스택에 표시됩니다. 이것은 특수 후크 때문입니까?
Tal

"다시 한 번, 실행 시점에 코드"줄 "이라는 개념은 자바 스크립트에서 더 이상 의미가 없습니다." 어? JS는 이미 줄 번호마다 당신을 console.log ()를 실행 보여줍니다
mikemaccana

@AnthonyWJones 예. 다소 절대적인 'No and No (No)'와 깔끔하게 모순된다.
mikemaccana 2010

@nailer : 2009 년에는 모든 주요 브라우저에서 내 대답이 모순됩니다. 당면한 질문은 자바 스크립트를 실행할 때 수신자의 회선 번호를 발견하는 것입니다.
AnthonyWJones 2011
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.