如何确定 JavaScript 中的当前行号?

问题描述 投票:0回答:11

JavaScript 是否有确定当前执行语句的行号的机制(如果有,是什么)?

javascript line-numbers
11个回答
87
投票

var thisline = new Error().lineNumber

如果这在您使用的任何环境下都不起作用,您可以尝试:

var stack = new Error().stack

然后在堆栈中寻找行号。


更新:

如果您在浏览器上进行调试,您可以在控制台部分下的窗口右侧看到当前正在运行的 console.log() 行。


60
投票

您可以使用:

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

test();

35
投票

在不同浏览器和浏览器版本之间更具可移植性(应该在 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];
}

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

2
投票

将以下代码片段插入您的代码中:

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

1
投票

你可以尝试:

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

然后在你想知道的地方抛出一个错误(不是太想要,但如果你正在调试,它可能会帮助你。

注意:

window.onerror
未在WebKitOpera中定义/处理(我上次检查时)


1
投票
const line = new Error().stack.match(/(:[\d]+)/)[0].replace(':','')
console.log(line)

1
投票

如果您使用node.js并且您关心获取行号的成本(可能不是最重要的事情),那么使用v8的调用点是我所知道的获取行号的最佳方法。

以下代码避免了将堆栈转换为文本的成本,并直接从

stack[1]
对象中提取调用者 (
callsites
) 行号。

  'use strict';

  function thisLine() {
    let line;
    const _prepareStackTrace = Error.prepareStackTrace;
    Error.prepareStackTrace = (_, stack) => {
      line = stack[1].getLineNumber();
    };
    const e = new Error();
    e.stack;
    Error.prepareStackTrace = _prepareStackTrace;

    return line;
  }

  if (require.main === module) {
    console.log('this line is', thisLine());
  }

请参阅 https://v8.dev/docs/stack-trace-api 了解文档。


0
投票

来源:git @tiagofrancafernandes


var getPos = (toGet = null) => {
    let stack = String(new Error().stack);
    let calledFrom = String((stack.split(`\n`)).filter(item => item).at(-1));
    calledFrom = calledFrom.startsWith('@') ? calledFrom.slice(1) : calledFrom;

    let items = {
        stack: stack,
        calledFrom: calledFrom,
    }

    let lineCol = String(calledFrom).match(/(\:)([0-9]){1,}(:([0-9]).?)$/g)[0];
    lineCol = String(lineCol).split(':').filter(item => item)
    items['lineCol'] = lineCol.join(':');
    items['line'] = lineCol.length == 2 ? lineCol[0] : null;
    items['col'] = lineCol.length == 2 ? lineCol[1] : null;

    toGet = toGet ? String(toGet) : null;

    if (toGet && !Object.keys(items).includes(toGet)) {
        return null;
    }

    return items[`${toGet}`] ?? items;
}

var __LINE__ = () => getPos('line');

// Usage
/*
    console.log(getPos())
    console.log(__LINE__())
    console.log(getPos('lineCol'))
    console.log(getPos('line'))
    console.log(getPos('col'))
    console.log(getPos('calledFrom'))
    console.log(getPos('stack'))
*/

-1
投票

纯粹无法从 Error.stack 中获取行号,因为在 Angular 中,行号就是编译后代码的行号。但我们可以获取错误是在哪一种方法中产生的信息。此代码片段中的 Logger 类将此信息添加到新的日志条目中。

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


-3
投票

如果您的代码是 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“字体增强”:Android 上的 Chrome 调整字体大小。将其视为每个网页都需要的样板。)

以下行只是为了验证我没有犯错误。在浏览器的调试器中查看,或者通过右键单击/保存网页,它会变成一个 HTML 注释,显示正确的源文件名和行号:

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

变成:

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

现在,无论我在哪里看到行号,无论是在错误消息中还是在 JavaScript 调试器中,它都是正确的。 PHP 行号和 JavaScript 行号始终一致且相同。

© www.soinside.com 2019 - 2024. All rights reserved.