Jak mogę określić aktualny numer linii w JavaScript?

Odpowiedzi:

72

var thisline = new Error().lineNumber

Jeśli to nie zadziała w jakimkolwiek środowisku, z którego korzystasz, możesz spróbować:

var stack = new Error().stack

Następnie przeszukaj stos w poszukiwaniu numeru linii.

z5h
źródło
3
Nie będzie działać w IE, lineNumberwłaściwość nie istnieje na obiektach błędów. Ani stack:-)
Andy E
1
gdzieś w IE jest numer linii. Wiem o tym, ponieważ kiedy mój javascript generuje błąd, mówi, że jest w wierszu o liczbie większej niż 100 milionów.
Malfist
nie do końca dostaję poprawną liczbę, to 1350, a powinno być 1250.
john-jones
1
Problem: jeśli używasz PHP, „kod źródłowy” widziany przez javascript nie jest oryginalnym kodem źródłowym, więc zawiera nieprawidłowe numery linii. (Prawdopodobnie to właśnie dzieje się z Hermannem.) Czy ktoś wie, jak sprawić, by javascript zobaczył oryginalne numery linii kodu źródłowego PHP? Rozwiązanie prawdopodobnie polega na wygenerowaniu „mapy źródłowej”, ale nie mogę znaleźć sposobu, aby to zrobić. Z pewnością jest to rozwiązany problem, prawda?
Dave Burton,
Uwaga: czasami numer stosu / wiersza nie jest dostępny podczas konstruowania obiektu Error, tylko wtedy, gdy jest on generowany, na przykład w Google Apps Script - w takim przypadku zobacz tę odpowiedź, aby uzyskać rozwiązanie.
user202729
41

Możesz użyć:

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

test();
baligena
źródło
2
Zdecydowanie najprostsze rozwiązanie i działa nawet na MS Edge.
Danger
27

Nieco bardziej przenośny między różnymi przeglądarkami i wersjami przeglądarek (powinien działać w Firefox, Chrome i 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];
}
jwatt
źródło
Dzięki. Dostosowałem twoją sugestię do tego: stackoverflow.com/a/37081135/470749
Ryan
1
Jeśli dostosujesz wyrażenie regularne, możesz zwrócić zarówno numery wierszy, jak i kolumn: var frameRE = /:(\d+:\d+)[^\d]*$/;co jest znacznie bardziej przydatne, szczególnie gdy JS jest zminimalizowany do jednej długiej linii.
Quinn Comendant
Uwaga, nie działa w skryptach ViolentMonkey dla Chrome - otrzymasz fałszywy numer, nie wiem dlaczego.
hanshenrik
5

Możesz spróbować przeanalizować źródło funkcji, aby wyszukać jakieś znaczniki.
Oto krótki przykład (tak, jest trochę pomieszany).

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;
}
Michaił Nasyrow
źródło
3

Wstaw następujący fragment kodu do swojego kodu:

console.debug("line:", /\(file:[\w\d/.-]+:([\d]+)/.exec(new Error().stack)[1]);
crishushu
źródło
w razie potrzeby zastąp nazwę protokołu (np. „http:”)
crishushu
1
Nie mogłem zmusić tego do pracy. Rozumiem TypeError: /\(http:[\w\d/.-]+:([\d]+)/.exec(...) is null.
Ryan
2

Możesz spróbować:

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

Następnie wyślij błąd tam, gdzie chcesz wiedzieć (niezbyt pożądane, ale może ci pomóc, jeśli debugujesz.

Uwaga: window.onerrornie jest zdefiniowany / obsługiwany w WebKit lub Opera (ostatni raz sprawdzałem)

scunliffe
źródło
1
Zauważ, że window.onerror nie działa w webkit: bugs.webkit.org/show_bug.cgi?id=8519
Annie,
1
Ciekawy. Można nawet utworzyć specjalną funkcję, throwAndResume(resumeFunction);która będzie przechowywać resumeFunction, zgłaszać błąd, aw dzienniku obsługi błędów szczegóły, a następnie wywołać resumeFunction, aby kontynuować program.
z5h
-3

Jeśli twój kod to JavaScript + PHP, to bieżący numer linii PHP jest dostępny w JavaScript jako stała dosłowna, ponieważ jest dostępny w PHP jako   <?= __LINE__ ?>

(Oczywiście zakładając, że masz włączone krótkie tagi PHP).

Na przykład w JavaScript możesz powiedzieć:

this_php_line_number = <?= __LINE__ ?>;

Jednakże, jeśli nie jesteś ostrożny, numer linii PHP może różnić się od numeru linii JavaScript, ponieważ PHP „zjada” linie źródłowe, zanim przeglądarka kiedykolwiek je zobaczy. Problem polega więc na upewnieniu się, że numery linii w PHP i JavaScript są takie same. Jeśli są różne, korzystanie z debugera JavaScript przeglądarki jest o wiele mniej przyjemne.

Możesz upewnić się, że numery wierszy są takie same, dołączając instrukcję PHP, która zapisuje poprawną liczbę nowych wierszy potrzebną do synchronizacji numerów wierszy po stronie serwera (PHP) i przeglądarki (JavaScript).

Oto jak wygląda mój kod:

<!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__); ?> *** -->

Kluczem jest ta instrukcja PHP:

echo str_repeat("\n",__LINE__-6);

To wypluwa wystarczająco dużo nowych linii, aby numer linii widziany przez JavaScript był taki sam, jak numer linii PHP. Wszystkie definicje funkcji PHP itp. Znajdują się na górze, przed tą linią.

Po tej linii ograniczam używanie PHP do kodu, który nie zmienia numerów linii.

Wartość „-6” odpowiada za to, że mój kod PHP zaczyna się w linii 8. Jeśli uruchomisz kod PHP wcześniej, zmniejszysz tę liczbę. Niektórzy ludzie umieszczają PHP na samym szczycie, nawet przed DOCTYPE.

(Linia meta viewport wyłącza „zwiększanie czcionek” w Androidzie Chrome zgodnie z tym pytaniem i odpowiedziami w przypadku przepełnienia stosu: Chrome na Androida zmienia rozmiar czcionki . Rozważ to szablon, którego potrzebuje każda strona internetowa).

Poniższy wiersz służy tylko do sprawdzenia, czy nie popełniłem błędu. Wyświetlany w debugerze przeglądarki lub po kliknięciu prawym przyciskiem myszy / zapisaniu strony internetowej, staje się komentarzem HTML, który pokazuje poprawną nazwę pliku źródłowego i numer wiersza:

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

staje się:

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

Teraz, gdziekolwiek widzę numer linii, czy to w komunikacie o błędzie, czy w debugerze JavaScript, jest poprawny. Numery linii PHP i numery linii JavaScript są zawsze spójne i identyczne.

Dave Burton
źródło