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

发布于 2024-08-22 17:22:33 字数 46 浏览 7 评论 0原文

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

Does JavaScript have a mechanism for determining the line number of the currently executing statement (and if so, what is it)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

も让我眼熟你 2024-08-29 17:22:33

var thisline = new Error().lineNumber

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

var stack = new Error().stack

然后在堆栈中寻找行号。


更新:

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

当前行在浏览器中运行的代码

var thisline = new Error().lineNumber

If that doesn't work in whatever environment you're using, you can try:

var stack = new Error().stack

Then hunt through the stack for the line number.


UPDATE:

If you are debugging on browser you can see current line of running console.log() on right side of window under console section.

Current line of code running in browser

愚人国度 2024-08-29 17:22:33

您可以使用:

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

test();

You can use:

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

test();
感受沵的脚步 2024-08-29 17:22:33

在不同浏览器和浏览器版本之间更便携(应该在 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];
}

A bit more portable between different browsers and browser versions (should work in Firefox, Chrome and 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];
}
万人眼中万个我 2024-08-29 17:22:33

您可以尝试解析函数的源代码来寻找一些标记。
这是一个简单的例子(是的,有点混乱)。

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

You can try to parse a source of a function to seek some marks.
Here is a quick example (yes, it's messed a little).

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;
}
滥情哥ㄟ 2024-08-29 17:22:33

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

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

Inject the following snippet to your code:

console.debug("line:", /\(file:[\w\d/.-]+:([\d]+)/.exec(new Error().stack)[1]);
找个人就嫁了吧 2024-08-29 17:22:33

您可以尝试:

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

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

注意: window.onerror 未在 WebKit歌剧(我上次检查时)

You can try:

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

Then throw an error where you want to know (not overly desired, but it might help you if you are debugging.

Note: window.onerror isn't defined/handled in WebKit or Opera (the last time I checked)

書生途 2024-08-29 17:22:33
const line = new Error().stack.match(/(:[\d]+)/)[0].replace(':','')
console.log(line)
const line = new Error().stack.match(/(:[\d]+)/)[0].replace(':','')
console.log(line)
初与友歌 2024-08-29 17:22:33

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

以下代码避免了将堆栈转换为文本的成本,并直接从 callsites 对象中提取调用者 (stack[1]) 行号。

  '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 了解文档。

If you're using node.js and you care about the cost of getting the line number (not likely the most important thing), then using v8's callsites is the best way I know of to get the line number.

The following code avoids the cost of converting the stack to text and extracts the callers (stack[1]) line number directly from the callsites object.

  '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());
  }

see https://v8.dev/docs/stack-trace-api for documentation.

她如夕阳 2024-08-29 17:22:33

来源: 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'))
*/

Source: 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'))
*/
桃扇骨 2024-08-29 17:22:33

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

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

Purely one can't get the line number out of Error.stack, because in Angular the line number is the line number of the compiled code. But one can get the info in which method the error was created. The class Logger in this code snippet add this piece of information to a new logbook entry.

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

萌面超妹 2024-08-29 17:22:33

如果您的代码是 JavaScript + PHP,则当前 PHP 行号在 JavaScript 中可用作文字常量,因为它在 PHP 中可用作  

(显然,这是假设您启用了 PHP 短标记。)

因此,例如,在 JavaScript 中您可以说:

this_php_line_number = <?= __LINE__ ?>;

但是,如果您不小心,PHP 行number 可能与 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 之前。

(元视口行根据此 StackOverflow 问答禁用 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 行号始终一致且相同。

If your code is JavaScript + PHP, then the current PHP line number is available in JavaScript as a literal constant, because it's available in PHP as   <?= __LINE__ ?>

(That's assuming you have PHP short tags enabled, obviously.)

So, for example, in JavaScript you can say:

this_php_line_number = <?= __LINE__ ?>;

However, if you are not careful, the PHP line number might be different from the JavaScript line number, because PHP "eats" source lines before the browser ever sees them. So the problem becomes ensuring that your PHP and JavaScript line numbers are the same. If they're different it makes using the browser's JavaScript debugger a lot less pleasant.

You can ensure the line numbers are the same by including a PHP statement that writes the correct number of newlines needed to synchronize server-side (PHP) and browser-side (JavaScript) line numbers.

Here's what my code looks like:

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

The key is this PHP statement:

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

That spits out enough newlines to make the line number seen by JavaScript be the same as the PHP line number. All the PHP function definitions, etc. are at the top, ahead of that line.

After that line, I restrict my use of PHP to code that doesn't change the line numbers.

The "-6" accounts for the fact that my PHP code starts on line 8. If you start your PHP code earlier, you'll reduce that number. Some people put their PHP right at the very top, even ahead of the DOCTYPE.

(The meta viewport line disables Android Chrome "font boosting" per this Stack Overflow Q&A: Chrome on Android resizes font. Consider it boilerplate, which every web page needs.)

The following line is just for verifying that I haven't made a mistake. Viewed in the browser's debugger, or by right-click / save-web-page, it becomes an HTML comment which shows the correct source file name and line number:

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

becomes:

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

Now, wherever I see a line number, whether it's in an error message or in the JavaScript debugger, it's correct. PHP line numbers and JavaScript line numbers are always consistent and identical.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文