在 V8 JavaScript (Chrome & Node.js) 中访问行号

Posted

技术标签:

【中文标题】在 V8 JavaScript (Chrome & Node.js) 中访问行号【英文标题】:Accessing line number in V8 JavaScript (Chrome & Node.js) 【发布时间】:2012-07-08 08:18:37 【问题描述】:

使用过 C 等语言的 javascript 开发人员经常错过使用某些类型的自省的能力,例如记录行号,以及调用当前方法的方法。好吧,如果您使用的是 V8(Chrome、Node.js),您可以使用以下内容。

【问题讨论】:

【参考方案1】:

IMO 接受的答案的问题在于,当您想要打印某些内容时,您可能正在使用记录器,而在这种情况下,使用接受的解决方案将始终打印同一行 :)

一些小的改动将有助于避免这种情况!

在我们的例子中,我们使用 Winston 进行日志记录,所以 the code 看起来像这样(注意下面的 code-cmets):

/**
 * Use CallSite to extract filename and number, for more info read: https://v8.dev/docs/stack-trace-api#customizing-stack-traces
 * @returns string filename and line number separated by a colon
 */
const getFileNameAndLineNumber = () => 
    const oldStackTrace = Error.prepareStackTrace;
    try 
        // eslint-disable-next-line handle-callback-err
        Error.prepareStackTrace = (err, structuredStackTrace) => structuredStackTrace;
        Error.captureStackTrace(this);
        // in this example I needed to "peel" the first CallSites in order to get to the caller we're looking for
        // in your code, the number of stacks depends on the levels of abstractions you're using
        // in my code I'm stripping frames that come from logger module and winston (node_module)
        const callSite = this.stack.find(line => line.getFileName().indexOf('/logger/') < 0 && line.getFileName().indexOf('/node_modules/') < 0);
        return callSite.getFileName() + ':' + callSite.getLineNumber();
     finally 
        Error.prepareStackTrace = oldStackTrace;
    
;

【讨论】:

这是另一个很好的解决方案。我的答案是很久以前写的,但我相信我对arguments.callee.caller 的引用也是为了解决您在此处提出的问题 @james_womack arguments.callee.caller 并不总是可以访问的(在我的 nodejs 应用程序中不是)。另外:eslint.org/docs/rules/no-caller 但我想在你写答案的时候使用它是可以的:) 明白——你说的有道理 arguments.callee 从 ES5 严格模式中移除:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…【参考方案2】:
Object.defineProperty(global, '__stack', 
  get: function()
    var orig = Error.prepareStackTrace;
    Error.prepareStackTrace = function(_, stack) return stack; ;
    var err = new Error;
    Error.captureStackTrace(err, arguments.callee);
    var stack = err.stack;
    Error.prepareStackTrace = orig;
    return stack;
  
);

Object.defineProperty(global, '__line', 
  get: function()
    return __stack[1].getLineNumber();
  
);

console.log(__line);

以上将记录19

结合arguments.callee.caller,您可以更接近通过宏在 C 中获得的有用日志类型。

【讨论】:

code.google.com/p/v8/wiki/… 列出了 v8 StackTrace API 中可用的其他方法。通用列表:getThis、getTypeName、getFunction、getFunctionName、getMethodName、getFileName、getLineNumber、getColumnNumber、getEvalOrigin、isToplevel、isEval、isNative、isConstructor 另请参阅此答案以获取一些示例代码以输出整个跟踪。 ***.com/questions/6163807/… 可以在此处查看此 API 的一些示例用法:github.com/jameswomack/capn/blob/master/test/capn.js @zamnuts 该页面似乎不再列出任何这些功能 2019年v8堆栈跟踪API文档地址为v8.dev/docs/stack-trace-api

以上是关于在 V8 JavaScript (Chrome & Node.js) 中访问行号的主要内容,如果未能解决你的问题,请参考以下文章

Chrome V8基本介绍

`IOS`或`MacOs` Chrome浏览器上的`JS引擎`是`V8`?还是`JavaScript Code`?

浏览器是如何工作的:Chrome V8让你更懂JavaScript

图解Google V8,搞懂 JavaScript 执行逻辑

浏览器是如何工作的:Chrome V8让你更懂JavaScript

JavaScript 引擎「V8」发布 8.0 版本,内存占用量大幅下降