Как получить номер строки функции вызывающего абонента 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 и в этом среднем посте в блоге.