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

IT技术 javascript node.js google-chrome v8
2021-02-26 11:43:46

花时间在像 C 这样的语言中的 JavaScript 开发人员经常错过使用某些类型的自省的能力,比如记录行号,以及调用当前方法的方法。好吧,如果您使用的是 V8(Chrome、Node.js),则可以使用以下内容。

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 中获得的有用日志记录类型。

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

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

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

在我们的例子中,我们使用 Winston 进行日志记录,因此代码如下所示(注意下面的代码注释):

/**
 * 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也是关于解决你在这里提出的问题
2021-04-22 11:43:46
@james_womackarguments.callee.caller并不总是可以访问的(在我的 nodejs 应用程序中不是)。另外:eslint.org/docs/rules/no-caller但我想在你写答案的时候使用它是可以的:)
2021-04-29 11:43:46
arguments.callee从 ES5 严格模式中移除:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-05-06 11:43:46
理解——你说的有道理
2021-05-16 11:43:46