Как получить номер строки функции вызывающего абонента JavaScript? Как получить URL-адрес исходного кода JavaScript-звонящего?

Я использую следующее для получения имени функции вызывающего JavaScript:

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

Есть ли способ узнать номер строки, из которой был вызван метод?

Кроме того, есть ли способ получить имя файла JavaScript, из которого был вызван метод? Или исходный URL?

Ответ 1

Это работает для меня в chrome/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);

Ответ 2

Да. Здесь кросс-браузерная функция, которая использует запатентованные методы каждого браузера:

http://github.com/eriwen/javascript-stacktrace

[фиксированная ссылка]

Ответ 3

Решение kangax вводит ненужную область try..catch. Если вам нужно получить доступ к номеру строки чего-либо в JavaScript (если вы используете Firefox или Opera), просто войдите в (new Error).lineNumber.

Ответ 4

Я был удивлен, что большинство из этих ответов предполагало, что вы хотели обработать ошибку, а не просто выводить полезные трассировки отладки для обычных случаев.

Например, мне нравится использовать обертку console.log следующим образом:

consoleLog = function(msg) {//See /questions/62483/how-can-i-determine-the-current-line-number-in-javascript/430713#430713470749
    var e = new Error();
    if (!e.stack)
        try {
            // IE requires the Error to actually be thrown or else the 
            // Error '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 [[email protected]://me.com/helper.js:362:9]

См. fooobar.com/questions/62483/..., а также Собственная оболочка для console.log с правильным номером строки?

Ответ 5

Это часто достигается путем выброса ошибки из текущего контекста; затем анализ объекта ошибки для таких свойств, как lineNumber и fileName (что у некоторых браузеров)

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

Также помните, что декомпиляция функции указана как зависящая от реализации и, следовательно, может дать совершенно неожиданные результаты. Я написал об этом здесь и здесь.

Ответ 6

Кажется, я немного опаздываю:), но дискуссия довольно интересная, поэтому... здесь она идет... Предполагая, что вы хотите создать обработчик ошибок, и вы используете свой собственный класс обработчика исключений, например:

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 error консоль номер строки кода (и имя файла) показал строку (файл), которая выдает исключение "Ошибка", а не исключение "errorHandler", которое вы действительно хотите в порядке чтобы сделать отладку легкой. Выброс собственных исключений велик, но в крупных проектах их размещение может быть довольно проблематичным, особенно если у них есть похожие сообщения. Итак, что вы можете сделать, это передать ссылку на фактический пустой объект Error на ваш обработчик ошибок, и эта ссылка будет содержать всю необходимую информацию (например, в firefox вы можете получить имя файла, номер строки и т.д.; в chrome вы получите что-то подобное, если вы читаете свойство "stack" экземпляра Error). Короче говоря, вы можете сделать что-то вроде этого:

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

Теперь вы можете получить фактический номер файла и строки, который выбрал пользовательское исключение.

Ответ 7

Если вы хотите узнать номер строки для целей отладки или только во время разработки (по той или иной причине), вы можете использовать Firebug (расширение Firefox) и throw исключение.

Edit

Если вам действительно нужно сделать это в производстве по какой-то причине, вы можете предварительно обработать ваши файлы javascript, чтобы каждая функция отслеживала линию, в которой она находится. Я знаю некоторые рамки, которые используют этот код для использования кода (например, 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);
}

Ответ 8

Номер строки на самом деле является чем-то статическим, поэтому, если вы просто хотите его записывать, он может быть предварительно обработан с чем-то вроде gulp. Я написал небольшой плагин 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). Преимущество в том, что теперь вы можете конкатенировать свои файлы, перетащить их... и вы все равно получите строку

Ответ 9

Вот что я написал на основе информации, найденной на этом форуме:

Это часть пространства 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 и номер строки как undefined.

Ответ 10

следующий код работает для меня в 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);
}

Ответ 11

Мой вклад в пользовательские ошибки в JavaScript:

  • Во-первых, я согласен с этим парнем @BT в Наследовании от объекта Error - где это свойство сообщения?, мы должны его правильно построить ( на самом деле вам нужно использовать библиотеку объектов 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;
    
  • тогда мы должны определить глобальную функцию обработки ошибок (необязательно) или, в конце концов, к движку:

    window.onerror = printError; 
    function printError(msg, url, line){
        document.getElementById('test').innerHTML = msg+'<br>at: '+url+'<br>line: '+line;
        return true;
    }
    
  • наконец, мы должны тщательно бросить наши пользовательские ошибки:

    //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 функция также может обрабатывать ошибки, выдаваемые двигателем.

Конечно, реальный вопрос в том, действительно ли нам это нужно и когда; есть случаи (на 99%, на мой взгляд), где достаточно грациозного возврата false и оставить только некоторые критические точки, которые будут показаны с ошибкой.

Пример: http://jsfiddle.net/centurianii/m2sQ3/1/

Ответ 12

Вот как я это сделал, я тестировал его как в 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);
    }
}

Ответ 13

Ответы просты. Нет и Нет (Нет).

К тому времени, когда javascript запускает концепцию исходных файлов/URL-адресов, с которых происходит переход.

Также нет способа определить номер строки, потому что снова к моменту выполнения понятие "строки" кода больше не имеет смысла в Javascript.

Конкретные реализации могут предоставлять API-интерфейсы, позволяющие обеспечить доступ к привилегированным кодам таким деталям с целью отладки, но эти API не подвергаются обычным стандартным Javascript-кодом.

Ответ 14

Чтобы определить, какая строка находится, вы должны искать весь код для кода, который занимает конкретную интересующую строку, и считать символы "\n" сверху и интереснее и добавить 1.

Я действительно делаю это в приложении, которое я пишу. Это эффективный валидатор для HTML и по-прежнему находится в стадии разработки, но процесс вывода ошибок, который вас интересует, завершен.

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

Ответ 15

console.log(new Error);

Он покажет вам весь трек.

Ответ 16

Я понимаю, что это старый вопрос, но теперь существует метод с именем console.trace("Message"), который покажет вам номер строки и цепочку вызовов методов, которые привели к журналу, а также сообщение, которое вы передаете. Больше информации о хитростях регистрации в javascript доступно здесь на freecodecamp и в этом среднем посте в блоге.