用ES6语法和Babel扩展Javascript的错误

我试图用ES6和Babel来扩展Error。 这不是工作。

class MyError extends Error { constructor(m) { super(m); } } var error = new Error("ll"); var myerror = new MyError("ll"); console.log(error.message) //shows up correctly console.log(myerror.message) //shows empty string 

错误对象从来没有得到正确的消息集。

试试Babel REPL 。

现在我已经看到了一些关于SO的解决scheme( 例如这里 ),但是他们都看起来非常不合适ES6-Y。 如何在一个不错的,ES6的方式呢? (这是在巴别塔工作)

根据KarelBílek的回答,我会对constructor做一些小改动:

 class ExtendableError extends Error { constructor(message) { super(message); this.name = this.constructor.name; if (typeof Error.captureStackTrace === 'function') { Error.captureStackTrace(this, this.constructor); } else { this.stack = (new Error(message)).stack; } } } // now I can extend class MyError extends ExtendableError {} var myerror = new MyError("ll"); console.log(myerror.message); console.log(myerror instanceof Error); console.log(myerror.name); console.log(myerror.stack); 

这将在堆栈中打印MyError ,而不是通用的Error

它还会将错误消息添加到堆栈跟踪中 – 这是从Karel的示例中缺less的。

如果可用,它也将使用captureStackTrace

对于Babel 6,您需要使用内置变换 ( npm )来实现此function。

结合这个答案 , 这个答案和这个代码 ,我做了这个小的“帮手”类,似乎工作正常。

 class ExtendableError extends Error { constructor(message) { super(); this.message = message; this.stack = (new Error()).stack; this.name = this.constructor.name; } } // now I can extend class MyError extends ExtendableError { constructor(m) { super(m); } } var myerror = new MyError("ll"); console.log(myerror.message); console.log(myerror instanceof Error); console.log(myerror.name); console.log(myerror.stack); 

尝试在REPL

终于把这个rest了。 在Babel 6中,显然开发人员不支持从内置扩展。尽pipe这个技巧对于像MapSet等类似的东西是没有帮助的,但是对于Error却是有效的。 这是非常重要的,因为可以抛出exception的语言的核心思想之一就是允许自定义错误。 这是双重重要的,因为承诺变得更有用,因为它们旨在拒绝错误 。

可悲的事实是你仍然需要在ES2015中以旧的方式表演。

Babel REPL中的示例

自定义错误模式

 class MyError { constructor(message) { this.name = 'MyError'; this.message = message; this.stack = new Error().stack; // Optional } } MyError.prototype = Object.create(Error.prototype); 

另一方面,Babel 6有一个插件允许这样做。

https://www.npmjs.com/package/babel-plugin-transform-b​​uiltin-extend

更新:(截至2016年9月29日)经过一些testing,似乎babel.io没有适当地考虑所有的断言(从一个自定义的扩展错误延伸)。 但在Ember.JS扩展错误按预期工作: https ://ember-twiddle.com/d88555a6f408174df0a4c8e0fd6b27ce

编辑 :打破Typescript 2.1中的更改

扩展像Error,Array和Map之类的内置程序可能不再有效。

作为build议,您可以在任何超级(…)调用之后立即手动调整原型。

编辑李本森原来的答案有点为我工作。 这也将ExtendableError类的stack和其他方法添加到实例中。

 class ExtendableError extends Error { constructor(message) { super(message); Object.setPrototypeOf(this, ExtendableError.prototype); this.name = this.constructor.name; } dump() { return { message: this.message, stack: this.stack } } } class MyError extends ExtendableError {} var myerror = new MyError("ll"); console.log(myerror.message); console.log(myerror.dump()); console.log(myerror instanceof Error); console.log(myerror.name); console.log(myerror.stack); 

引用

 class MyError extends Error { constructor(message) { super(message); this.message = message; this.name = 'MyError'; } } 

不需要this.stack = (new Error()).stack; 特技感谢super()调用。

虽然上面的代码不能输出堆栈跟踪,除非this.stack = (new Error()).stack;Error.captureStackTrace(this, this.constructor.name); 在巴别被援引。 海事组织,这可能是一个问题在这里。

实际上,可以使用此代码片段在Chrome consoleNode.js v4.2.1下输出堆栈跟踪。

 class MyError extends Error{ constructor(msg) { super(msg); this.message = msg; this.name = 'MyError'; } }; var myerr = new MyError("test"); console.log(myerr.stack); console.log(myerr); 

Chrome console输出。

 MyError: test at MyError (<anonymous>:3:28) at <anonymous>:12:19 at Object.InjectedScript._evaluateOn (<anonymous>:875:140) at Object.InjectedScript._evaluateAndWrap (<anonymous>:808:34) at Object.InjectedScript.evaluate (<anonymous>:664:21) 

Node.js输出

 MyError: test at MyError (/home/bsadmin/test/test.js:5:8) at Object.<anonymous> (/home/bsadmin/test/test.js:11:13) 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 

除了@zangw答案,你可以像这样定义你的错误:

 'use strict'; class UserError extends Error { constructor(msg) { super(msg); this.name = this.constructor.name; } } // define errors class MyError extends UserError {} class MyOtherError extends UserError {} console.log(new MyError instanceof Error); // true throw new MyError('My message'); 

这将引发正确的名称,消息和堆栈跟踪:

 MyError: My message at UserError (/Users/honzicek/Projects/api/temp.js:5:10) at MyError (/Users/honzicek/Projects/api/temp.js:10:1) at Object.<anonymous> (/Users/honzicek/Projects/api/temp.js:14:7) at Module._compile (module.js:434:26) at Object.Module._extensions..js (module.js:452:10) at Module.load (module.js:355:32) at Function.Module._load (module.js:310:12) at Function.Module.runMain (module.js:475:10) at startup (node.js:117:18) at node.js:951:3 

我正在尝试扩展错误与ES6

class MyError extends Error {…}语法是正确的。

请注意,转译器仍然存在从内build对象inheritance的问题。 在你的情况下,

 var err = super(m); Object.assign(this, err); 

似乎解决了这个问题。

鉴于这个被接受的答案不再起作用,你总是可以使用一个工厂作为替代( repl ):

 function ErrorFactory(name) { return class AppError extends Error { constructor(message) { super(message); this.name = name; this.message = message; if (typeof Error.captureStackTrace === 'function') { Error.captureStackTrace(this, this.constructor); } else { this.stack = (new Error(message)).stack; } } } } // now I can extend const MyError = ErrorFactory("MyError"); var myerror = new MyError("ll"); console.log(myerror.message); console.log(myerror instanceof Error); console.log(myerror.name); console.log(myerror.stack); 

正如@sukima提到的,你不能扩展原生的JS。 OP的问题不能回答。

与Melbourne2991的答案类似,我确实使用了工厂,但遵循MDN对客户错误types的build议 。

 function extendError(className){ function CustomError(message){ this.name = className; this.message = message; this.stack = new Error().stack; // Optional } CustomError.prototype = Object.create(Error.prototype); CustomError.prototype.constructor = CustomError; return CustomError; } 

随着babel 6的最新变化,我发现转换内置扩展不再有效。 最后,我最终使用了这种混合的方法:

 export default class MyError { constructor (message) { this.name = this.constructor.name; this.message = message; this.stack = (new Error(message)).stack; } } MyError.prototype = Object.create(Error.prototype); MyError.prototype.constructor = MyError; 

 import MyError from './MyError'; export default class MyChildError extends MyError { constructor (message) { super(message); } } 

结果所有这些testing通过:

 const sut = new MyError('error message'); expect(sut.message).toBe('error message'); expect(sut).toBeInstanceOf(Error); expect(sut).toBeInstanceOf(MyError); expect(sut.name).toBe('MyError'); expect(typeof sut.stack).toBe('string'); const sut = new MyChildError('error message'); expect(sut.message).toBe('error message'); expect(sut).toBeInstanceOf(Error); expect(sut).toBeInstanceOf(MyError); expect(sut).toBeInstanceOf(MyChildError); expect(sut.name).toBe('MyChildError'); expect(typeof sut.stack).toBe('string'); 
Interesting Posts