从本机Error类继承时如何覆盖.stack?

时间:2015-10-26 12:25:52

标签: javascript node.js ecmascript-6

(节点版本'4.2.1',v8'4.5.103.35')

var TE = class tError extends Error {
   constructor(message) {
      super(message);
      this.name = tError.name;
      Error.captureStackTrace(this, tError);
   }
   static prepareStackTrace() {
      console.log('run is prepareStackTrace');
      return 'MyPrepareStack'
   }
   get stack() {
      console('getter stack');
      return 'MyStack';
   }
};

TE.stackTraceLimit = 1;

console.log('ErrorPrepare:', TE.prepareStackTrace);

var e = new TE('MyError');
console.log('ErrorName: ', e.name);
console.log('ErrorStack: ', e.stack);

输出:

D:\>node ./Error
ErrorPrepare: prepareStackTrace() {
      console.log('run is prepareStackTrace');
      return 'MyPrepareStack'
   }
ErrorName:  tError
ErrorStack:  tError: MyError
    at Object.<anonymous> (D:\Error.js:23:9)
    at Module._compile (module.js:435:26)
    at Object.Module._extensions..js (module.js:442:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Function.Module.runMain (module.js:467:10)
    at startup (node.js:134:18)
    at node.js:961:3

在本机属性和方法上没有工作类getter。未调用类声明中指定的函数。

如何修改本机类中的本机属性和本机行为?

1 个答案:

答案 0 :(得分:0)

因此您在使用本机 Error.prepareStackTrace 时不会继承。事实上,Error.prepareStackTrace 的工作方式与您在标准 ES JavaScript 库中看到的典型 API 完全不同,这是因为它是原生的。通常(或历史上)JavaScript 会实现回调来分配格式化数据的函数,但因为我们正在配置 V8 使用的函数,何时可以为此使用回调。

简单来说,为了让答案尽可能简短:Native 意味着 V8 可以识别它,并且可以使用它。 V8 无法识别大多数 JavaScript 内容,因为它定义了它,但错误是任何语言的基本组成部分,这也是为什么错误格式在 V8 JavaScript 环境(Chrome 和 Node.js)中是原生的一个重要部分。 JavaScript 中的堆栈跟踪必须默认格式化,据我所知,大多数 JS 引擎只传递一个不可定制的字符串作为堆栈跟踪,无论我们在什么 JavaScript 环境中传播和拦截,我们看到的字符串都是一样的错误。这样浏览器制造商(或开发人员)和 JS RTE 软件工程师都可以以相同的方式解析堆栈跟踪,从而使 JS 错误兼容几乎没有空间,如果有的话,出现问题。 (我希望我解释得很好。)

因此,没有继承,Error.prepareStackTrace 的工作方式在下面我在 2016 年写的东西中进行了解释,大约是在问这个问题的时候。到 2021 年的今天,它仍然是相关的。

我写了一个笔记列表,详细描述了如何使用它,我将在下面发布。此 Error 属性有该做的不该做的...堆栈跟踪)...所以做你的功课。

  • 以下是我几年前写的指南文档。虽然它已经有几年的历史了,但它在今天仍然非常重要。指南注释很好地描述了 Error.prepareStackTrace

  • 注释下方的一些链接在解释此主题时非常有用。

01| Error.prepareStackTrace


下面的代码片段演示了一个基本用例,也许是最常见的 Error.prepareStackTrace 用例。




   ​'use strict';

   ​const callsites = () => {
     ​const _prepareStackTrace = Error.prepareStackTrace;

     ​Error.prepareStackTrace = (_, stack) => stack;

     ​const stack = new Error().stack.slice(1);
     ​Error.prepareStackTrace = _prepareStackTrace;

     ​return stack;
   ​};


  1. Error.prepareStackTrace 是通过使用赋值运算符 (=) 来配置的,以将函数分配给 Error.prepareStackTrace。 JavaScript 通常在这种情况下使用回调,因此,对于某些人来说,这种语法可能会让人感到尴尬。

  2. 分配给 Error.prepareStackTrace 的函数应该有两个参数。第一个参数接受错误对象,第二个参数接受*错误对象的堆栈跟踪。您不会调用 Error.prepareStackTrace 的分配函数 ever -- 每次捕获堆栈跟踪时,V8 引擎都会调用 Error.prepareStackTrace(更多关于捕获堆栈跟踪的信息如下) ).

  3. Error.captureStackTrace 方法负责捕获堆栈跟踪。

  4. Error.prepareStackTraceError.captureStackTrace 都是原生 V8 JavaScript 函数,都可用于 Node.js RTE(在 v16.2.0 期间编写)。浏览器不支持这两种功能。

  5. 如上所述,Error.prepareStackTrace 由 V8 引擎自动调用。发生这种情况时,分配给 Error.prepareStackTrace 的函数参数会自动传递其参数。参数包括一个错误对象,以及错误对象的堆栈跟踪(这也在上面说明,如果你的困惑是因为你跳来跳去,没有按顺序阅读列表。)

  6. 上面代码片段返回的堆栈可以通过以下方法调用来操作,只要数据可用即可。仅仅因为该方法可用并不意味着该方法的数据可用。

  7. 以下是可用于错误返回的堆栈跟踪的调用站点方法列表,并由 Error.prepareStackTrace 的指定函数格式化。

  8. 据我所知:“一旦调用堆栈被捕获,在被捕获时调用堆栈中的每一帧都会成为一个调用站点,下面的方法列表是 V8 CallSite API——API用于提取存储在调用站点中的任何数据。"


  • getThis:返回 this 的值
  • getTypeName:以字符串形式返回 this 的类型。这是存储在 this 的构造函数字段中的函数的名称(如果可用),否则是对象的 [[Class]] 内部属性。
  • getFunction:返回当前函数
  • getFunctionName:返回当前函数的名称,通常是它的 name 属性。如果名称属性不可用,则会尝试从函数的上下文中推断名称。
  • getMethodName:返回保存当前函数的 this 或其原型之一的属性名称
  • getFileName:如果这个函数是在脚本中定义的,则返回脚本的名称
  • getLineNumber:如果这个函数是在脚本中定义的,则返回当前行号
  • getColumnNumber:如果此函数在脚本中定义,则返回当前列号
  • getEvalOrigin:如果此函数是使用对 eval 的调用创建的,则返回一个字符串,表示调用 eval 的位置
  • isToplevel:这是一个顶级调用,也就是说,这是全局对象吗?
  • isEval:此调用是否发生在由调用 eval 定义的代码中?
  • isNative:这个调用是在原​​生 V8 代码中吗?
  • isConstructor:这是一个构造函数调用吗?
  • isAsync:这是一个异步调用(即 await 或 Promise.all())?
  • isPromiseAll:这是对 Promise.all() 的异步调用吗?
  • getPromiseIndex:返回 Promise.all() 中用于异步堆栈跟踪的 promise 元素的索引,如果 CallSite 不是 Promise.all() 调用,则返回 null。




链接:

  1. V8 Official Documentation

  2. Codota Code Examples

  3. NPM Module that implements Error.prepareStackTrace for you. -- 大多数人都选择这条路线,因为如果你决定喜欢它,并且你开始在所有项目中使用它,那么每次下载模块都会变得更容易,而不是重写它,或者尝试为它维护自己的模块。我在上面发布的代码片段与此 NPM 模块使用的代码片段相同,它是一个代码片段,您可以在 Codota、StackOVerflow 和其他地方找到不同版本的代码片段。研究并学习我上面发布的代码片段,您将掌握原生 V8 错误属性。