Як я можу визначити поточний номер рядка в JavaScript?


97

Чи має JavaScript механізм для визначення номера рядка поточно виконуваного оператора (і якщо так, то що це)?


Відповіді:


71

var thisline = new Error().lineNumber

Якщо це не працює в будь-якому середовищі, яке ви використовуєте, спробуйте:

var stack = new Error().stack

Потім подивіться через стек на номер рядка.


3
Не буде працювати в IE, lineNumberвластивість не існує для об’єктів помилок. Також ні stack:-)
Енді Е

1
десь на IE є номер рядка. Я знаю це, тому що коли мій javascript видає помилку, це означає, що він знаходиться на рядку із числом більше 100 мільйонів.
Малфіст

я не зовсім отримую правильне число, його 1350, коли має бути 1250.
Fzs2

1
Проблема: якщо ви використовуєте PHP, "вихідний код", який бачить javascript, не є оригінальним вихідним кодом, тому він має неправильні номери рядків. (Це, мабуть, те, що відбувається з Германом.) Хтось знає, як зробити так, щоб javascript бачив оригінальні номери рядків вихідного коду PHP? Рішення, ймовірно, передбачає якусь генерацію "вихідної карти", але я не можу знайти, як це зробити. Напевно це вирішена проблема, так ??
Dave Burton

Примітка: іноді номер стека / рядка недоступний, коли побудований об’єкт Помилка, лише коли він викинутий, наприклад, у Google Apps Script - у такому випадку див. Цю відповідь для рішення.
user202729

39

Ви можете використовувати:

function test(){
    console.trace();
}

test();

1
На сьогоднішній день найпростіше рішення, і воно працює навіть на MS Edge.
Небезпека

27

Трохи портативніший між різними браузерами та версіями браузера (повинен працювати у 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];
}

Дякую. Я адаптував вашу пропозицію до цього: stackoverflow.com/a/37081135/470749
Райан

1
Якщо ви відрегулюєте регулярний вираз, ви можете повернути номери рядків і стовпців: var frameRE = /:(\d+:\d+)[^\d]*$/;що набагато корисніше, особливо коли JS зменшується в один довгий рядок.
Quinn Comendant

Попередження, не працює у сценаріях ViolentMonkey для Chrome - ви отримаєте фіктивну цифру, не знаю чому.
hanshenrik

5

Ви можете спробувати проаналізувати джерело функції, щоб знайти деякі позначки.
Ось короткий приклад (так, це трохи переплутано).

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

3

Введіть у свій код такий фрагмент:

console.debug("line:", /\(file:[\w\d/.-]+:([\d]+)/.exec(new Error().stack)[1]);

замінити ім'я протоколу за необхідності (наприклад, "http:")
crishushu

1
Я не міг змусити це працювати. Я розумію TypeError: /\(http:[\w\d/.-]+:([\d]+)/.exec(...) is null.
Райан

2

Ви можете спробувати:

window.onerror = handleError;
function handleError(err, url, line){
    alert(err + '\n on page: ' + url + '\n on line: ' + line);
}

Потім викиньте помилку там, де ви хочете знати (не надто бажане, але це може допомогти вам, якщо ви налагоджуєте.

Примітка: window.onerrorне визначається / не обробляється в WebKit або Opera (останній раз, коли я перевіряв)


1
Зверніть увагу, що помилка window.oner не працює у webkit: bugs.webkit.org/show_bug.cgi?id=8519
Енні

1
Цікаво. Ви навіть можете створити спеціальну функцію, throwAndResume(resumeFunction);яка зберігатиме resumeFunction, видалятиме помилку, а у вашому журналі обробника помилок - деталі, а потім викликати resumeFunction, щоб продовжити програму.
z5h

0

Чисто не вдається вивести номер рядка з Error.stack, оскільки в Angular номер рядка - це номер рядка скомпільованого коду. Але можна отримати інформацію, яким методом була створена помилка. Клас Logger у цьому фрагменті коду додає цю інформацію до нового запису журналу.

https://stackblitz.com/edit/angular-logger?file=src/app/Logger/logger.ts


-2

Якщо ваш код 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

...lots of 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>

...lots of HTML and 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 відповідно до цього запитання та відповіді Stack Overflow: Chrome на Android змінює розмір шрифту . Розгляньте його як шаблон, який потрібен кожній веб-сторінці.)

Наступний рядок призначений лише для підтвердження того, що я не помилився. Переглядаючись у налагоджувачі браузера або клацнувши правою кнопкою миші / збереження веб-сторінки, він стає коментарем HTML, який показує правильне ім'я вихідного файлу та номер рядка:

<!-- *** this is line <?php echo __LINE__ . ' of ' . basename(__FILE__); ?> *** -->

стає:

<!-- *** this is line 1234 of my_file.php *** -->

Тепер, де б я не бачив номер рядка, будь то в повідомленні про помилку або в налагоджувачі JavaScript, це правильно. Номери рядків PHP та номери рядків JavaScript завжди узгоджені та однакові.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.