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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11386492/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 05:41:02  来源:igfitidea点击:

Accessing line number in V8 JavaScript (Chrome & Node.js)

javascriptnode.jsgoogle-chromev8

提问by james_womack

JavaScript developers who have spent time in languages like C often miss the ability to use certain types of introspection, like logging line numbers, and what method the current method was invoked from. Well if you're using V8 (Chrome, Node.js) you can employ the following.

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

回答by james_womack

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

The above will log 19.

以上将登录19

Combined with arguments.callee.calleryou can get closer to the type of useful logging you get in C via macros.

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

回答by alfasin

The problem with the accepted answer, IMO, is that when you want to print something you might be using a logger, and when that is the case, using the accepted solution will always print the same line :)

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

Some minor changes will help avoiding such a case!

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

In our case, we're using Winston for logging, so the codelooks like this (pay attention to the code-comments below):

在我们的例子中,我们使用 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;
    }
};