我想在我的JS代码中抛出一些东西,我想让它们成为instanceof Error,但我也想让它们成为其他东西。
在Python中,通常会子类化Exception。
在JS中应该做什么?
我想在我的JS代码中抛出一些东西,我想让它们成为instanceof Error,但我也想让它们成为其他东西。
在Python中,通常会子类化Exception。
在JS中应该做什么?
当前回答
除了标准的message属性,JavaScript现在支持将特定的错误原因作为可选参数添加到error构造函数中:
const error1 = new Error('Error one');
const error2 = new Error('Error two', { cause: error1 });
// error2.cause === error1
在节点v16.9.0中提供。 适用于Chrome, Firefox和Safari(见浏览器兼容性版本)
其他回答
在2018年,我认为这是最好的方式;支持IE9+和现代浏览器。
更新:请参阅此测试和repo以了解不同实现的比较。
function CustomError(message) {
Object.defineProperty(this, 'name', {
enumerable: false,
writable: false,
value: 'CustomError'
});
Object.defineProperty(this, 'message', {
enumerable: false,
writable: true,
value: message
});
if (Error.hasOwnProperty('captureStackTrace')) { // V8
Error.captureStackTrace(this, CustomError);
} else {
Object.defineProperty(this, 'stack', {
enumerable: false,
writable: false,
value: (new Error(message)).stack
});
}
}
if (typeof Object.setPrototypeOf === 'function') {
Object.setPrototypeOf(CustomError.prototype, Error.prototype);
} else {
CustomError.prototype = Object.create(Error.prototype, {
constructor: { value: CustomError }
});
}
还要注意__proto__属性已弃用,该属性在其他答案中广泛使用。
Crescent Fresh的答案是误导性的。尽管他的警告是无效的,但还有其他一些限制他没有提到。
首先,Crescent的“警告:”段落中的推理没有意义。这种解释意味着,与多个catch语句相比,编码“一堆if (error instanceof MyError) else…”在某种程度上是累赘或冗长的。单个catch块中的多个instanceof语句与多个catch语句一样简洁——干净简洁的代码,没有任何技巧。这是模拟Java出色的特定于可抛出子类型的错误处理的好方法。
WRT“显示子类的消息属性没有得到设置”,如果使用正确构造的Error子类,则不会出现这种情况。要创建自己的ErrorX Error子类,只需复制以"var MyError ="开头的代码块,将"MyError"改为"ErrorX"。(如果您想向子类添加自定义方法,请遵循示例文本)。
The real and significant limitation of JavaScript error subclassing is that for JavaScript implementations or debuggers that track and report on stack trace and location-of-instantiation, like FireFox, a location in your own Error subclass implementation will be recorded as the instantiation point of the class, whereas if you used a direct Error, it would be the location where you ran "new Error(...)"). IE users would probably never notice, but users of Fire Bug on FF will see useless file name and line number values reported alongside these Errors, and will have to drill down on the stack trace to element #1 to find the real instantiation location.
Mohsen has a great answer above in ES6 that sets the name, but if you're using TypeScript or if you're living in the future where hopefully this proposal for public and private class fields has moved past stage 3 as a proposal and made it into stage 4 as part of ECMAScript/JavaScript then you might want to know this is then just a little bit shorter. Stage 3 is where browsers start implementing features, so if your browser supports it the code below just might work. (Tested in the new Edge browser v81 it seems to work fine). Be warned though this is an unstable feature at the moment and should be used cautiously and you should always check browser support on unstable features. This post is mainly for those future dwellers when browsers might support this. To check support check MDN and Can I use. It's currently got 66% support across the browser market which is getting there but not that great so if you really want to use it now and don't want to wait either use a transpiler like Babel or something like TypeScript.
类EOFError扩展错误{ name = " EOFError " } 抛出新的EOFError("Oops error ");
将此与一个无名错误进行比较,该错误在抛出时不会记录其名称。
类NamelessEOFError扩展错误{} 抛出新的NamelessEOFError("Oops error ");
在上面的例子中。apply (also Error.call)不为我做任何事情(Firefox 3.6/Chrome 5)。我使用的一个变通方法是:
function MyError(message, fileName, lineNumber) {
var err = new Error();
if (err.stack) {
// remove one stack level:
if (typeof(Components) != 'undefined') {
// Mozilla:
this.stack = err.stack.substring(err.stack.indexOf('\n')+1);
}
else if (typeof(chrome) != 'undefined' || typeof(process) != 'undefined') {
// Google Chrome/Node.js:
this.stack = err.stack.replace(/\n[^\n]*/,'');
}
else {
this.stack = err.stack;
}
}
this.message = message === undefined ? err.message : message;
this.fileName = fileName === undefined ? err.fileName : fileName;
this.lineNumber = lineNumber === undefined ? err.lineNumber : lineNumber;
}
MyError.prototype = new Error();
MyError.prototype.constructor = MyError;
MyError.prototype.name = 'MyError';
这段代码显示了这一切。
function add(x, y) {
if (x && y) {
return x + y;
} else {
/**
*
* the error thrown will be instanceof Error class and InvalidArgsError also
*/
throw new InvalidArgsError();
// throw new Invalid_Args_Error();
}
}
// Declare custom error using using Class
class Invalid_Args_Error extends Error {
constructor() {
super("Invalid arguments");
Error.captureStackTrace(this);
}
}
// Declare custom error using Function
function InvalidArgsError(message) {
this.message = `Invalid arguments`;
Error.captureStackTrace(this);
}
// does the same magic as extends keyword
Object.setPrototypeOf(InvalidArgsError.prototype, Error.prototype);
try{
add(2)
}catch(e){
// true
if(e instanceof Error){
console.log(e)
}
// true
if(e instanceof InvalidArgsError){
console.log(e)
}
}