Comment puis-je déterminer le numéro de ligne actuel dans JavaScript?

Réponses:

69

var thisline = new Error().lineNumber

Si cela ne fonctionne pas dans l'environnement que vous utilisez, vous pouvez essayer:

var stack = new Error().stack

Cherchez ensuite dans la pile le numéro de ligne.

z5h
la source
3
Ne fonctionnera pas dans IE, la lineNumberpropriété n'existe pas sur les objets d'erreur. Ni fait stack:-)
Andy E
1
il y a un numéro de ligne quelque part sur IE. Je le sais parce que lorsque mon javascript jette une erreur, il dit que c'est sur une ligne avec un nombre supérieur à 100 millions.
Malfist
Je n'ai pas tout à fait le bon numéro, son 1350 alors qu'il devrait être 1250.
Fzs2
1
Problème: si vous utilisez PHP, le "code source" vu par javascript n'est pas le code source d'origine, il a donc les mauvais numéros de ligne. (C'est probablement ce qui arrive à Hermann.) Est-ce que quelqu'un sait comment faire en sorte que javascript voie les numéros de ligne du code source PHP d'origine? La solution implique probablement une sorte de génération de "source map", mais je ne trouve pas comment le faire. C'est sûrement un problème résolu, non ??
Dave Burton
Remarque: parfois, le numéro de pile / ligne n'est pas disponible lorsque l'objet Error est construit, uniquement lorsqu'il est lancé, par exemple dans Google Apps Script - dans ce cas, consultez cette réponse pour la solution.
user202729
38

Vous pouvez utiliser:

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

test();
Baligena
la source
1
De loin la solution la plus simple et elle fonctionne même sur MS Edge.
Danger
27

Un peu plus portable entre différents navigateurs et versions de navigateur (devrait fonctionner dans Firefox, Chrome et 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
la source
Merci. J'ai adapté votre suggestion à ceci: stackoverflow.com/a/37081135/470749
Ryan
1
Si vous ajustez l'expression régulière, vous pouvez renvoyer les numéros de ligne et de colonne: var frameRE = /:(\d+:\d+)[^\d]*$/;ce qui est beaucoup plus utile, en particulier lorsque le JS est réduit en une seule longue ligne.
Quinn Comendant
Attention, ne fonctionne pas dans les scripts ViolentMonkey pour Chrome - vous obtiendrez un faux numéro, je ne sais pas pourquoi.
hanshenrik
5

Vous pouvez essayer d'analyser une source d'une fonction pour rechercher des marques.
Voici un exemple rapide (oui, c'est un peu foiré).

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;
}
Mikhail Nasyrov
la source
3

Injectez l'extrait de code suivant dans votre code:

console.debug("line:", /\(file:[\w\d/.-]+:([\d]+)/.exec(new Error().stack)[1]);
Crishushu
la source
remplacez le nom du protocole si nécessaire (par exemple "http:")
crishushu
1
Je n'ai pas pu faire fonctionner cela. Je reçois TypeError: /\(http:[\w\d/.-]+:([\d]+)/.exec(...) is null.
Ryan
2

Tu peux essayer:

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

Ensuite, lancez une erreur là où vous voulez savoir (pas trop désiré, mais cela pourrait vous aider si vous déboguez.

Remarque: window.onerrorn'est pas défini / géré dans WebKit ou Opera (la dernière fois que j'ai vérifié)

scunliffe
la source
1
Notez que window.onerror ne fonctionne pas dans le webkit
Annie
1
Intéressant. Vous pouvez même créer une fonction spéciale throwAndResume(resumeFunction);qui stockerait resumeFunction, lèverait l'erreur et, dans votre gestionnaire d'erreurs, consignait les détails, puis appelait resumeFunction pour continuer votre programme.
z5h le
0

On ne peut pas extraire le numéro de ligne de Error.stack, car dans Angular, le numéro de ligne est le numéro de ligne du code compilé. Mais on peut obtenir des informations dans quelle méthode l'erreur a été créée. La classe Logger de cet extrait de code ajoute cette information à une nouvelle entrée de journal.

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

Viree
la source
-2

Si votre code est JavaScript + PHP, le numéro de ligne PHP actuel est disponible dans JavaScript en tant que constante littérale, car il est disponible en PHP sous la forme   <?= __LINE__ ?>

(Cela suppose que vous avez activé les balises PHP courtes, évidemment.)

Ainsi, par exemple, en JavaScript, vous pouvez dire:

this_php_line_number = <?= __LINE__ ?>;

Cependant, si vous ne faites pas attention, le numéro de ligne PHP peut être différent du numéro de ligne JavaScript, car PHP «mange» les lignes source avant que le navigateur ne les voie. Le problème consiste donc à s'assurer que vos numéros de ligne PHP et JavaScript sont les mêmes. S'ils sont différents, l'utilisation du débogueur JavaScript du navigateur est beaucoup moins agréable.

Vous pouvez vous assurer que les numéros de ligne sont les mêmes en incluant une instruction PHP qui écrit le nombre correct de retours à la ligne nécessaire pour synchroniser les numéros de ligne côté serveur (PHP) et côté navigateur (JavaScript).

Voici à quoi ressemble mon code:

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

La clé est cette déclaration PHP:

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

Cela crache suffisamment de nouvelles lignes pour que le numéro de ligne vu par JavaScript soit le même que le numéro de ligne PHP. Toutes les définitions de fonctions PHP, etc. sont en haut, avant cette ligne.

Après cette ligne, je limite mon utilisation de PHP au code qui ne change pas les numéros de ligne.

Le "-6" explique le fait que mon code PHP commence à la ligne 8. Si vous démarrez votre code PHP plus tôt, vous réduirez ce nombre. Certaines personnes placent leur PHP tout en haut, même devant le DOCTYPE.

(La ligne de la méta-fenêtre désactive le "renforcement de la police" d'Android Chrome conformément à ce Q&R de Stack Overflow: Chrome sur Android redimensionne la police . Considérez-le comme une version standard, dont chaque page Web a besoin.)

La ligne suivante est juste pour vérifier que je n'ai pas fait d'erreur. Vu dans le débogueur du navigateur, ou par clic droit / save-web-page, il devient un commentaire HTML qui montre le nom du fichier source correct et le numéro de ligne:

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

devient:

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

Maintenant, partout où je vois un numéro de ligne, que ce soit dans un message d'erreur ou dans le débogueur JavaScript, c'est correct. Les numéros de ligne PHP et les numéros de ligne JavaScript sont toujours cohérents et identiques.

Dave Burton
la source