Как я могу определить текущий номер строки в JavaScript?
Есть ли в JavaScript механизм определения номера строки выполняемого в данный момент оператора (и если да, то что это)?
11 ответов
var thisline = new Error().lineNumber
Если это не работает в любой среде, которую вы используете, вы можете попробовать:
var stack = new Error().stack
Затем поищите в стеке номер строки.
Ты можешь использовать
function test(){
console.trace();
}
test();
Немного более переносимо между различными браузерами и версиями браузера (должно работать в Firefox, Chrome и IE10+):
function ln() {
var e = new Error();
if (!e.stack) try {
// IE requires the Error to actually be throw 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/);
// We want our caller's frame. It's index into |stack| depends on the
// browser and browser version, so we need to search for the second frame:
var frameRE = /:(\d+):(?:\d+)[^\d]*$/;
do {
var frame = stack.shift();
} while (!frameRE.exec(frame) && stack.length);
return frameRE.exec(stack.shift())[1];
}
Вы можете попытаться проанализировать источник функции, чтобы найти некоторые метки.
Вот быстрый пример (да, это немного запутано).
function foo()
{
alert(line(1));
var a;
var b;
alert(line(2));
}
foo();
function line(mark)
{
var token = 'line\\(' + mark + '\\)';
var m = line.caller.toString().match(
new RegExp('(^(?!.*' + token + '))|(' + token + ')', 'gm')) || [];
var i = 0;
for (; i < m.length; i++) if (m[i]) break;
return i + 1;
}
Вставьте следующий фрагмент в ваш код:
console.debug("line:", /\(file:[\w\d/.-]+:([\d]+)/.exec(new Error().stack)[1]);
Ты можешь попробовать:
window.onerror = handleError;
function handleError(err, url, line){
alert(err + '\n on page: ' + url + '\n on line: ' + line);
}
затем выдать ошибку, которую вы хотите знать (не слишком желательно, но она может помочь вам, если вы отлаживаете).
Замечания: window.onerror
не определяется / не обрабатывается в WebKit или Opera (последний раз, когда я проверял)
Если вы используете node.js и вам небезразлична стоимость получения номера строки (вероятно, не самая важная вещь), то использование callsites v8 — это лучший известный мне способ получить номер строки.
Следующий код позволяет избежать затрат на преобразование стека в текст и извлекает вызывающие объекты (stack[1]
) номер строки непосредственно изcallsites
объект.
'use strict';
function thisLine() {
let line;
const _prepareStackTrace = Error.prepareStackTrace;
Error.prepareStackTrace = (_, stack) => {
line = stack[1].getLineNumber();
};
const e = new Error();
e.stack;
Error.prepareStackTrace = _prepareStackTrace;
return line;
}
if (require.main === module) {
console.log('this line is', thisLine());
}
см. https://v8.dev/docs/stack-trace-api для документации.
const line = new Error().stack.match(/(:[\d]+)/)[0].replace(':','')
console.log(line)
Источник: git @tiagofrancafernandes
var getPos = (toGet = null) => {
let stack = String(new Error().stack);
let calledFrom = String((stack.split(`\n`)).filter(item => item).at(-1));
calledFrom = calledFrom.startsWith('@') ? calledFrom.slice(1) : calledFrom;
let items = {
stack: stack,
calledFrom: calledFrom,
}
let lineCol = String(calledFrom).match(/(\:)([0-9]){1,}(:([0-9]).?)$/g)[0];
lineCol = String(lineCol).split(':').filter(item => item)
items['lineCol'] = lineCol.join(':');
items['line'] = lineCol.length == 2 ? lineCol[0] : null;
items['col'] = lineCol.length == 2 ? lineCol[1] : null;
toGet = toGet ? String(toGet) : null;
if (toGet && !Object.keys(items).includes(toGet)) {
return null;
}
return items[`${toGet}`] ?? items;
}
var __LINE__ = () => getPos('line');
// Usage
/*
console.log(getPos())
console.log(__LINE__())
console.log(getPos('lineCol'))
console.log(getPos('line'))
console.log(getPos('col'))
console.log(getPos('calledFrom'))
console.log(getPos('stack'))
*/
Чисто невозможно получить номер строки из Error.stack, потому что в Angular номер строки - это номер строки скомпилированного кода. Но можно узнать, каким методом возникла ошибка. Класс Logger в этом фрагменте кода добавляет эту информацию в новую запись журнала.
https://stackblitz.com/edit/angular-logger?file=src/app/Logger/logger.ts
Если ваш код javascript + PHP, то текущий номер строки PHP доступен в javascript как буквальная константа, потому что он доступен в PHP как <?= __LINE__ ?>
(Это предполагает, что у вас включены короткие теги PHP, очевидно.)
Так, например, в javascript вы можете сказать:
this_php_line_number = <?= __LINE__ ?>;
Однако, если вы не будете осторожны, номер строки в PHP может отличаться от номера строки в javascript, потому что PHP "ест" исходные строки до того, как их увидит браузер. Таким образом, проблема заключается в том, что номера строк в PHP и javascript совпадают. Если они отличаются, это делает использование отладчика javascript в браузере гораздо менее приятным.
Вы можете убедиться, что номера строк одинаковы, включив оператор PHP, который записывает правильное количество новых строк, необходимых для синхронизации номеров строк на стороне сервера (PHP) и на стороне браузера (javascript).
Вот как выглядит мой код:
<!DOCTYPE html>
<html lang="en">
<!-- Copyright 2016, 2017, me and my web site -->
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, user-scalable=yes">
<?php
...lottsa PHP stuff here, including all PHP function definitions ...
echo str_repeat("\n",__LINE__-6); # synchronize PHP and Javascript line numbers
?>
<!-- *** this is line <?php echo __LINE__ . ' of ' . basename(__FILE__); ?> *** -->
<title>My web page title</title>
...lottsa HTML & Javascript stuff here...
</body>
</html>
<!-- *** this is line <?php echo __LINE__ . ' of ' . basename(__FILE__); ?> *** -->
Ключ это выражение PHP:
echo str_repeat("\n",__LINE__-6);
Это выдает достаточно новых строк, чтобы номер строки, видимый в javascript, совпадал с номером строки в PHP. Все определения функций PHP и т. Д. Находятся вверху, перед этой строкой.
После этой строки я ограничиваю свое использование PHP кодом, который не меняет номера строк.
"-6" учитывает тот факт, что мой PHP-код начинается в строке 8. Если вы запустите PHP-код раньше, вы уменьшите это число. Некоторые люди ставят свой PHP на самый верх, даже перед DOCTYPE.
(Строка метапортпорта отключает Android Chrome для "повышения шрифта" в соответствии с этим стековым потоком. Вопросы и ответы: Chrome для Android изменяет размер шрифта. Рассмотрим его как шаблон, который необходим каждой веб-странице.)
Следующая строка просто для подтверждения того, что я не ошибся. При просмотре в отладчике браузера или по щелчку правой кнопкой мыши / сохранить веб-страницу он становится комментарием HTML, который показывает правильное имя исходного файла и номер строки:
<!-- *** this is line <?php echo __LINE__ . ' of ' . basename(__FILE__); ?> *** -->
будет выглядеть так:
<!-- *** this is line 1234 of my_file.php *** -->
Теперь, где бы я ни увидел номер строки, будь то в сообщении об ошибке или в отладчике javascript, это правильно. Номера строк PHP и номера строк JavaScript всегда согласованы и идентичны.