Como posso determinar o número da linha atual em JavaScript?

Respostas:

72

var thisline = new Error().lineNumber

Se isso não funcionar em qualquer ambiente que estiver usando, você pode tentar:

var stack = new Error().stack

Em seguida, procure na pilha o número da linha.

z5h
fonte
3
Não funcionará no IE, a lineNumberpropriedade não existe em objetos de erro. Nem stack:-)
Andy E
1
há um número de linha em algum lugar do IE. Eu sei disso porque quando meu javascript lança um erro, ele diz que está em uma linha com um número maior que 100 milhões.
Malfist
não entendi bem o número correto, é 1350 quando deveria ser 1250.
john-jones
1
Problema: se você estiver usando PHP, o "código-fonte" visto pelo javascript não é o código-fonte original, então tem os números de linha errados. (Isso é provavelmente o que está acontecendo com Hermann.) Alguém sabe como fazer o javascript ver os números das linhas do código-fonte PHP original? A solução provavelmente envolve algum tipo de geração de "mapa de origem", mas não consigo descobrir como fazer isso. Com certeza esse é um problema resolvido, certo ??
Dave Burton
Nota: às vezes, o número da pilha / linha não está disponível quando o objeto Error é construído, apenas quando é lançado, por exemplo, no Google Apps Script - nesse caso, veja esta resposta para a solução.
user202729
41

Você pode usar:

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

test();
Baligena
fonte
2
De longe a solução mais simples e funciona até no MS Edge.
Perigo de
27

Um pouco mais portátil entre diferentes navegadores e versões de navegador (deve funcionar no Firefox, Chrome e 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
fonte
Obrigado. Adaptei sua sugestão para isto: stackoverflow.com/a/37081135/470749
Ryan
1
Se você ajustar o regex, poderá retornar os números de linha e coluna: o var frameRE = /:(\d+:\d+)[^\d]*$/;que é muito mais útil, principalmente quando o JS é reduzido em uma linha longa.
Quinn Comendant
Aviso, não funciona em scripts ViolentMonkey para Chrome - você obterá um número falso, não sei por quê.
hanshenrik
5

Você pode tentar analisar a origem de uma função para buscar algumas marcas.
Aqui está um exemplo rápido (sim, está um pouco confuso).

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
fonte
3

Injete o seguinte snippet em seu código:

console.debug("line:", /\(file:[\w\d/.-]+:([\d]+)/.exec(new Error().stack)[1]);
Crishushu
fonte
substitua o nome do protocolo conforme necessário (por exemplo, "http:")
crishushu
1
Eu não conseguia fazer isso funcionar. Eu entendo TypeError: /\(http:[\w\d/.-]+:([\d]+)/.exec(...) is null.
Ryan
2

Podes tentar:

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

Em seguida, lance um erro onde você deseja saber (não muito desejado, mas pode ajudá-lo se você estiver depurando.

Nota: window.onerrornão é definido / tratado no WebKit ou Opera (a última vez que verifiquei)

Scunliffe
fonte
1
Observe que window.onerror não funciona no webkit: bugs.webkit.org/show_bug.cgi?id=8519
Annie
1
Interessante. Você poderia até criar uma função especial throwAndResume(resumeFunction);que armazenaria resumeFunction, geraria o erro e, em seu log do manipulador de erros, os detalhes e chamaria resumeFunction para continuar seu programa.
z5h
0

Simplesmente não se pode obter o número da linha de Error.stack, porque no Angular o número da linha é o número da linha do código compilado. Mas pode-se obter a informação de qual método o erro foi criado. A classe Logger neste trecho de código adiciona esta informação a uma nova entrada do logbook.

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

Viree
fonte
-3

Se seu código for JavaScript + PHP, o número da linha atual do PHP está disponível em JavaScript como uma constante literal, porque está disponível em PHP como   <?= __LINE__ ?>

(Isso presumindo que você tenha tags curtas do PHP ativadas, obviamente.)

Então, por exemplo, em JavaScript, você pode dizer:

this_php_line_number = <?= __LINE__ ?>;

No entanto, se você não for cuidadoso, o número da linha do PHP pode ser diferente do número da linha do JavaScript, porque o PHP "come" as linhas de origem antes que o navegador as veja. Portanto, o problema passa a ser garantir que os números de linha do PHP e do JavaScript sejam iguais. Se forem diferentes, o uso do depurador de JavaScript do navegador será muito menos agradável.

Você pode garantir que os números das linhas sejam os mesmos incluindo uma instrução PHP que grava o número correto de novas linhas necessárias para sincronizar os números de linha do lado do servidor (PHP) e do lado do navegador (JavaScript).

Aqui está a aparência do meu código:

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

A chave é esta declaração PHP:

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

Isso gera novas linhas suficientes para fazer o número da linha visto pelo JavaScript ser igual ao número da linha do PHP. Todas as definições de função PHP, etc. estão no topo, à frente dessa linha.

Depois dessa linha, eu restrinjo meu uso de PHP a código que não altera os números das linhas.

O "-6" explica o fato de que meu código PHP começa na linha 8. Se você iniciar seu código PHP antes, reduzirá esse número. Algumas pessoas colocam seu PHP bem no topo, até mesmo à frente do DOCTYPE.

(A linha da janela de visualização meta desativa o "aumento de fonte" do Android Chrome de acordo com as perguntas e respostas do Stack Overflow: o Chrome no Android redimensiona a fonte . Considere-o padrão, que toda página da web precisa.

A linha a seguir serve apenas para verificar se não cometi um erro. Visualizado no depurador do navegador ou clicando com o botão direito / salvar página da web, torna-se um comentário HTML que mostra o nome do arquivo de origem correto e o número da linha:

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

torna-se:

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

Agora, sempre que vejo um número de linha, seja em uma mensagem de erro ou no depurador de JavaScript, está correto. Os números das linhas PHP e JavaScript são sempre consistentes e idênticos.

Dave Burton
fonte