Error.captureStackTrace(targetObject[, constructorOpt)
在 targetObject 上创建一个 .stack 属性,将以字符串的形式返回 Error.captureStackTrace() 语句被调用时的代码位置信息(即:调用栈历史)。
只能在 Node.js 和 Chrome 浏览器中使用。
与 new Error().stack 类似,后者使用范围更广,两者都能使用的情况下,优先使用 Error.captureStackTrace,理由是:
无需 new 一个新的 Error 对象,节省内存空间,同时代码上也会更加优雅;如果需要忽略部分堆栈信息,使用 Error.captureStackTrace 会更加方便,无需手工操作;如果使用 Error.captureStackTrace,则对于堆栈信息的格式化工作会被延迟至访问 targetObj.stack 时进行,如果 targetObject.stack 未被访问,则堆栈信息的格式化工作会被省略,从而节省计算资源。为了不向使用者暴露自定义Error类的内部细节,在自定义Error类内部使用 captureStackTrace 时,往往会传入 constructorOpt 参数,其值即为自定义 Error类的构造函数。我们用个例子来说一说这个参数的作用:
class CError() { constructor(type, detail) { Error.captureStackTrace(this, this.constructor); } //类的其他操作,项目不同各不相同 ... }我创建了一个 CError 的自定义错误类,现在产生了一个注册用户时用户名已存在的 error,在没设 constructorOpt 属性, targetObj.stack 的调用栈历史是这样的:
Error.captureStackTrace(this) "CError: 用户名已存在 at new CError (/Users/zyf/myStudy/demo/chatroom/utils/server/Error.js:40:11) at register (/Users/zyf/myStudy/demo/chatroom/server/controller/user.js:9:23) at process._tickCallback (internal/process/next_tick.js:68:7)"设了 constructorOpt 属性,是这样的:
"CError: 用户名已存在 at register (/Users/zyf/myStudy/demo/chatroom/server/controller/user.js:9:23) at process._tickCallback (internal/process/next_tick.js:68:7)"设了 constructorOpt 属性,就会隐藏掉 CError 内的内部调用信息。
设置属性的方法随构造函数的不同,大致分为2类:
Error.captureStackTrace(this, MyError); 将构造函数的变量名作为 constructorOpt 参数传入。
function CError() { Error.captureStackTrace(this, CError); }Error.captureStackTrace(this, this.constructor);通过this.constructor 传入constructorOpt 参数。
class CError() { constructor() { Error.captureStackTrace(this, this.constructor); } }其实还有一种在构造函数中将 arguments.callee 作为 constructorOpt 参数传入,因为已经不推荐使用 arguments.callee 了,所以这种方法也不推荐使用。