JavaScript dispose-t-il d'un mécanisme pour déterminer le numéro de ligne de l'instruction en cours d'exécution (et si oui, de quoi s'agit-il)?
JavaScript dispose-t-il d'un mécanisme pour déterminer le numéro de ligne de l'instruction en cours d'exécution (et si oui, de quoi s'agit-il)?
Réponses:
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.
lineNumber
propriété n'existe pas sur les objets d'erreur. Ni fait stack
:-)
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];
}
var frameRE = /:(\d+:\d+)[^\d]*$/;
ce qui est beaucoup plus utile, en particulier lorsque le JS est réduit en une seule longue ligne.
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;
}
Injectez l'extrait de code suivant dans votre code:
console.debug("line:", /\(file:[\w\d/.-]+:([\d]+)/.exec(new Error().stack)[1]);
TypeError: /\(http:[\w\d/.-]+:([\d]+)/.exec(...) is null
.
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.onerror
n'est pas défini / géré dans WebKit ou Opera (la dernière fois que j'ai vérifié)
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.
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
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.