在V8 JavaScript(Chrome&;Node.js)中访问行号
花时间学习C等语言的JavaScript开发人员常常无法使用某些类型的内省,例如记录行号,以及调用当前方法的方法。如果您使用的是V8(Chrome,Node.js),那么您可以采用以下方法在V8 JavaScript(Chrome&;Node.js)中访问行号,javascript,node.js,google-chrome,v8,Javascript,Node.js,Google Chrome,V8,花时间学习C等语言的JavaScript开发人员常常无法使用某些类型的内省,例如记录行号,以及调用当前方法的方法。如果您使用的是V8(Chrome,Node.js),那么您可以采用以下方法 Object.defineProperty(global, '__stack', { get: function(){ var orig = Error.prepareStackTrace; Error.prepareStackTrace = function(_, stack){ ret
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
结合
参数.callee.caller
您可以更接近通过宏在C中获得的有用日志记录类型。接受的答案IMO的问题是,当您想要打印某些内容时,您可能正在使用记录器,在这种情况下,使用接受的解决方案将始终打印同一行:)
一些小的改变将有助于避免这种情况
在我们的例子中,我们使用Winston进行日志记录,所以看起来是这样的(请注意下面的代码注释):
/**
*使用CallSite提取文件名和编号,有关详细信息,请阅读:https://v8.dev/docs/stack-trace-api#customizing-堆栈跟踪
*@返回{string}文件名和由冒号分隔的行号
*/
常量GetFileName和LineNumber=()=>{
const oldStackTrace=Error.prepareStackTrace;
试一试{
//eslint禁用下一行句柄回调错误
Error.prepareStackTrace=(err,structuredStackTrace)=>structuredStackTrace;
错误。captureStackTrace(此);
//在本例中,我需要“剥离”第一个呼叫站点,以便找到我们正在寻找的呼叫方
//在代码中,堆栈的数量取决于所使用的抽象级别
//在我的代码中,我正在剥离来自logger模块和winston(node_模块)的帧
const callSite=this.stack.find(line=>line.getFileName().indexOf('/logger/')<0&&line.getFileName().indexOf('/node_modules/')<0);
返回callSite.getFileName()+':'+callSite.getLineNumber();
}最后{
Error.prepareStackTrace=oldStackTrace;
}
};
提供了v8 StackTrace API中可用的其他方法列表。一般列表:getThis、getTypeName、getFunction、getFunctionName、getMethodName、getFileName、getLineNumber、getColumnNumber、getEvalOrigin、isToplevel、isEval、isNative、IsConstructor另请参阅此答案,以获取输出整个跟踪的一些示例代码。您可以在这里看到此API的一些示例用法:@zamnuts该页面似乎不再列出这些函数中的任何函数2019年v8堆栈跟踪API文档的URL是另一个伟大的解决方案。我的答案是很久以前写的,但我相信我提到的arguments.callee.caller
是为了解决您在这里提出的问题well@james_womackarguments.callee.caller
不总是可访问的(在我的nodejs应用程序中不是)。还有:但是我想在你写答案的时候用它是可以的:)明白你说的是有道理的
/**
* 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;
}
};