资讯专栏INFORMATION COLUMN

关于Error.captureStackTrace

weakish / 1428人阅读

摘要:在一些程序中,有时会看到这一语句,用于处理堆栈信息。为了不向使用者暴露自定义类的内部细节,在自定义类内部使用时,往往会传入参数,其值即为自定义类的构造函数。

在一些Node.js程序中,有时会看到Error.captureStackTrace()这一语句,用于处理堆栈信息。该语句的标准定义是什么?如何使用?本文将就这些问题做一些探讨。

标准定义

从字面上来看,captureStackTrace应该是Error构造函数自身的一个方法。因此,很自然的想到从ECMAScript标准文档中寻找答案。不幸的是,在标准文档的19.5 Error Objects章节中,并未提及任何有关captureStackTrace的内容。看来,这一语句和语言的运行环境有关,并非由JavaScript标准所定义。

既然JavaScript语言标准中没有定义captureStackTrace,那就只能从Node.js的文档中去寻找答案了。Node.js中,关于Error.captureStackTrace的描述是这样的:

Error.captureStackTrace(targetObject[, constructorOpt])
targetObject中添加一个.stack属性。对该属性进行访问时,将以字符串的形式返回Error.captureStackTrace()语句被调用时的代码位置信息(即:调用栈历史)。

以下是一个最简单的例子:

const myObject = {};
Error.captureStackTrace(myObject);
myObject.stack  // 效果与`new Error().stack`类似
与`errorObject.stack`不同的是,`errorObject.stack `所返回的字符串的第一行一般遵循`ErrorType: message`的形式,而使用captureStackTrace所得到的字符串的第一行则一般以`targetObject .toString()`开头。

除了targetObject, captureStackTrace还接受一个类型为function的可选参数constructorOpt,当传递该参数时,调用栈中所有constructorOpt函数之上的信息(包括constructorOpt函数自身),都会在访问targetObject.stack时被忽略。当需要对终端用户隐藏内部的技术细节时,constructorOpt参数会很有用。比如:

function MyError() {
  Error.captureStackTrace(this, MyError);
}

// 如果没有向captureStackTrace传递MyError参数,则在访问.stack属性时,MyError及其内部信息将会出现在堆栈信息中。当传递MyError参数时,这些信息会被忽略。
new MyError().stack

进一步的探究发现,Error.captureStackTrace()并非Node.js所创造,而是源自V8引擎的Stack Trace API(事实上,Node.js的Error类中,所有与stack trace有关的内容均依赖于V8的Stack Trace API)。从语法上来说,Node.js中的Error.captureStackTrace()与V8引擎中所暴露的接口完全一致。

在浏览器领域,除了使用V8引擎的Google Chrome,其它浏览器中不存在Error.captureStackTrace()这一接口。

使用场景

由于Error.captureStackTrace()可以返回调用堆栈信息,因此在自定义Error类的内部经常会使用该函数,用以在error对象上添加合理的stack属性。上文中的MyError类即是一个最简单的例子。

为了不向使用者暴露自定义Error类的内部细节,在自定义Error类内部使用captureStackTrace时,往往会传入constructorOpt参数,其值即为自定义 Error类的构造函数。具体做法有3种:

Error.captureStackTrace(this, MyError); 将构造函数的变量名作为constructorOpt参数传入。这一做法比较简单、直接,但不利之处也比较明显:代码所要传达的是“忽略当前构造函数内部的堆栈调用信息”,而以具体的构造函数作为参数传入使得这一语句缺乏通用性,不利于程序的进一步抽象。

Error.captureStackTrace(this, this.constructor); 通过this.constructor传入constructorOpt参数。与上一种方法相比,这一方式更具通用性。在自定义Error类中使用captureStackTrace时,推荐采用该方法。

Error.captureStackTrace(this, arguments.callee);通过arguments.callee将“当前函数”作为constructorOpt参数传入。不过,由于ES5的strict模式中禁用了arguments.callee,因此不建议使用该写法。

除了自定义Error类的使用场景,在JavaScript程序中,当需要获知调用堆栈信息时,都可以通过调用Error.captureStackTrace()来实现。以往如果需要获知调用堆栈信息,一般的做法是抛出一个Error对象并立即加以捕捉,通过访问该对象的stack属性来获得调用堆栈。一个简单的例子如下:

try {
  throw new Error();
} catch (e) {
  // e.stack 中包含了堆栈数据,可以进行处理从而忽略不感兴趣的堆栈信息
}

与这种做法相比,可以很明显的看到,使用Error.captureStackTrace()会更简洁、易用,也更优雅;而这,也许就是V8中添加Error.captureStackTrace()的原因。

链接:http://blog.shaochuancs.com/about-error-capturestacktrace/

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80599.html

相关文章

  • JavaScript 中的错误处理机制

    摘要:错误处理在开发和调试过程中都显得尤为重要。跟全局函数有关的错误,在之后已经不再出现了内部错误。由引擎抛出的错误范围错误。事件任何没有的错误都会触发对象的事件。事件可以接收三个参数错误消息错误所在的和行号。 错误处理在开发和调试过程中都显得尤为重要。有些没有进行错误处理的应用,直接就将浏览器的错误展示给了用户,极大的降低了用户体验。比如有些很 low 的网站,打开某些页面就直接弹出 ob...

    AbnerMing 评论0 收藏0
  • 翻译-JavaScript异常和调用堆栈的处理

    摘要:调用堆栈实际上就是一个方法列表,按调用顺序保存所有在运行期被调用的方法。调用堆栈会将当前正在执行的函数调用压入堆栈,一旦函数调用结束,又会将它移出堆栈。 原文 JavaScript Errors and Stack Traces in Depth 调用栈Call Stack是如何工作的 栈是一个后进先出LIFO (Last in,First out)的数据结构。调用堆栈实际上就是一个方...

    adam1q84 评论0 收藏0
  • node错误处理与日志

    摘要:并不自带,需要引入库运行日志文件,此时在目录下就生成了今天的日志欢迎访问我的博客 node项目中的错误处理 node中Error对象的使用 使用captureStackTrace方法加入自带的错误信息 // Error对象自带的属性 Error.captureStackTrace // 如何使用captureStackTrace var obj = { message: so...

    GT 评论0 收藏0
  • 基础学习 - 在JS 中的继承

    摘要:继承方法原型链继承父类型子类型子类型的原型为父类型的一个实例对象这种继承方式把设置直接设置为对象子类就可以通过原型链访问父级所有的属性和方法了。但是缺点很明显,在创建子类的时候会调用调用两次父类的构造函数。 起因 最近在使用node-jsonwebtoken中发现了下面这个代码,感觉挺好看,于是就打算探索一些相关代码: showImg(https://segmentfault.com/...

    Taste 评论0 收藏0
  • 详解JS错误处理:前端JS/Vue/React/Iframe/跨域/Node

    摘要:错误上报机制发送数据因为请求本身也有可能会发生异常,而且有可能会引发跨域问题,一般情况下更推荐使用动态创建标签的形式进行上报。 js错误捕获 js错误的实质,也是发出一个事件,处理他 error实例对象 对象属性 message:错误提示信息 name:错误名称(非标准属性)宿主环境赋予 stack:错误的堆栈(非标准属性)宿主环境赋予 对象类型(7种) Synt...

    张利勇 评论0 收藏0

发表评论

0条评论

weakish

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<