Как получить номер строки функции вызывающего JavaScript? Как получить исходный URL звонящего из JavaScript?
Я использую следующее для получения имени функции вызывающей стороны JavaScript:
var callerFunc = arguments.callee.caller.toString();
callerFuncName = (callerFunc.substring(callerFunc.indexOf("function") + 8, callerFunc.indexOf("(")) || "anoynmous")
Есть ли способ узнать номер строки, с которой был вызван метод?
Кроме того, есть ли способ получить имя файла JavaScript, из которого был вызван метод? Или исходный URL?
18 ответов
Это работает для меня в 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);
Решение kangax вводит ненужную область try..catch. Если вам нужен доступ к номеру строки чего-либо в JavaScript (если вы используете Firefox или Opera), просто получите доступ (new Error).lineNumber
,
Да. Вот кросс-браузерная функция, которая использует собственные методы каждого браузера:
http://github.com/eriwen/javascript-stacktrace
[фиксированная ссылка]
Я был удивлен, что большинство из этих ответов предполагали, что вы хотите обработать ошибку, а не просто выводить полезные трассировки отладки и для обычных случаев.
Например, мне нравится использовать console.log
обертка, как это:
consoleLog = function(msg) {//See https://stackru.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]
См. /questions/29300682/kak-ya-mogu-opredelit-tekuschij-nomer-stroki-v-javascript/29300690#29300690 а также надлежащую оболочку для console.log с правильным номером строки?
Я понимаю, что это старый вопрос, но теперь есть метод под названием console.trace("Message")
это покажет вам номер строки и цепочку вызовов методов, которые привели к журналу вместе с сообщением, которое вы передаете. Более подробную информацию о хитростях регистрации в javascript можно найти здесь, на freecodecamp и в этом среднем посте.
Это часто достигается путем выдачи ошибки из текущего контекста; затем анализируя объект ошибки для таких свойств, как 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-е изд. в первую очередь).
Также помните, что декомпиляция функции определяется как зависящая от реализации и может привести к довольно неожиданным результатам. Я написал об этом здесь и здесь.
Кажется, я немного опоздал:), но обсуждение довольно интересное, так что... вот так... Предполагается, что вы хотите создать обработчик ошибок и используете свой собственный класс обработчика исключений, например:
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 в ваш обработчик ошибок, и эта ссылка будет содержать всю необходимую информацию (например, в 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();
}
Теперь вы можете получить фактический файл и номер строки, которая вызвала пользовательское исключение.
Вот как я это сделал, я проверял это и в 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);
}
}
Номер строки на самом деле является чем-то статичным, поэтому, если вы просто хотите, чтобы он записывался в журнал, он мог бы быть предварительно обработан чем-то вроде 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)
, Преимущество в том, что теперь вы можете объединять свои файлы, переносить их... и вы все равно получите строку
Если вам нужно что-то очень полное и точное, для v8 (имеется в виду NodeJS и Chrome) есть
stack-trace
пакет, который работал у меня:
https://www.npmjs.com/package/stack-trace
У этого есть несколько преимуществ: возможность создавать глубокие трассировки стека, возможность пересекать
async
вызывает и предоставляет полный URL-адрес скриптов для каждого кадра стека.
Вы можете найти дополнительную информацию об API отслеживания стека v8 здесь .
Если вам нужно что-то, что работает в других браузерах, есть этот пакет:
https://www.npmjs.com/package/stacktrace-js
Эта библиотека анализирует отформатированные строки трассировки стека, которые вы обычно видите в консоли devtools, что означает, что у нее есть доступ только к информации, которая фактически отображается в отформатированной дорожке стека - в отличие от API v8, вы не можете получить (среди прочего) полный URL-адрес скрипта в стековом фрейме.
Обратите внимание, что синтаксический анализ отформатированной трассировки стека является несколько хрупким подходом, поскольку это форматирование может измениться в браузерах, что приведет к поломке вашего приложения.
Насколько я знаю, нет более безопасной ставки на кроссбраузерность - если вам нужно что-то быстрое, точное и полное, работающее во всех браузерах, вам в значительной степени не повезло.
Если вы хотите узнать номер строки для целей отладки или только во время разработки (по той или иной причине), вы можете использовать Firebug (расширение Firefox) и вызвать исключение.
Редактировать:
Если вам действительно нужно сделать это в производственной среде по какой-то причине, вы можете предварительно обработать файлы 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);
}
Следующий код работает для меня в 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);
}
Мой вклад в пользовательские ошибки в JavaScript:
Во-первых, я согласен с этим парнем @B T в Наследовании от объекта 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
достаточно и оставьте только некоторые критические точки, которые будут показаны с ошибкой.
Вот что я написал на основе информации, найденной на этом форуме:
Это часть 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 не определены.
Чтобы определить, в какой строке что-то находится, вы должны найти во всем коде код, который занимает конкретную интересующую строку, и подсчитать символы "\n" сверху вниз и добавить интересующий их 1.
На самом деле я делаю именно это в приложении, которое пишу. Это средство проверки соответствия рекомендациям для HTML, которое все еще находится в стадии разработки, но процесс вывода ошибок, который вас заинтересует, завершен.
ГЛОБАЛЬНАЯ ОБРАБОТКА ОШИБОК ДЛЯ ВСЕХ ВАШИХ JS-КОДОВ
window.onerror = function (msg, url, lineNo, columnNo, error) {
// ... handle error ...
alert(msg + ' - ' + url + ' - ' + lineNo + ' - ' + columnNo);
return false;
}
работал во всех браузерах :)
для простого теста добавьте эту строку с ошибочным кодом в любую часть вашего js:
aa.ll.kk;//to fire a pure syntax error
Ответы просты. Нет и нет (нет).
К тому времени, когда javascript запускает концепцию исходных файлов / URL-адресов, исходящие из которых исчезли.
Также нет способа определить номер строки, потому что снова к моменту исполнения понятие кода "строки" больше не имеет смысла в Javascript.
Конкретные реализации могут предоставлять хуки API, чтобы разрешить доступ привилегированного кода к таким деталям с целью отладки, но эти API не подвергаются воздействию обычного стандартного кода Javascript.