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

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

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

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

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

Ответы [ 15 ]

89 голосов
/ 27 сентября 2010

Это работает для меня в 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);
23 голосов
/ 28 августа 2009
Решение

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

8 голосов
/ 06 мая 2016

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

Например, мне нравится использовать оболочку 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 с правильным номером строки?

4 голосов
/ 27 августа 2009

Это часто достигается путем выдачи ошибки из текущего контекста; затем анализируем объект ошибки для таких свойств, как 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 3-е изд.).

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

3 голосов
/ 30 августа 2016

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

3 голосов
/ 05 марта 2011

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

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 показанный номер строки кода (и имя файла) - это строка (файл), которая вызывает исключение «Ошибка», а не исключение «ОшибкаHandler», которое вы действительно хотите использовать сделать отладку легкой. Создание собственных исключений - это замечательно, но в больших проектах их обнаружение может стать проблемой, особенно если у них есть похожие сообщения. Итак, что вы можете сделать, это передать ссылку на фактический пустой объект 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();
}

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

2 голосов
/ 28 марта 2019

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

2 голосов
/ 27 августа 2009

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

Редактировать

Если вам действительно необходимо по какой-то причине сделать это в рабочей среде, вы можете предварительно обработать файлы 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);
}
1 голос
/ 02 марта 2017

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

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

  1. Во-первых, я согласен с этим парнем @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;
    
  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 эта функция также может обрабатывать ошибки, выдаваемые двигателем.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...