在Javascript中抛出自定义异常。使用哪种风格?

24
道格拉斯·克罗克福德建议像这样做:

throw {
    name: "System Error",
    message: "Something horrible happened."
};

但您也可以像这样做:
function IllegalArgumentException(message) {
    this.message = message;
}

throw new IllegalArgumentException("Argument cannot be less than zero");

接着执行:

try {
    //some code that generates exceptions
} catch(e) {    
    if(e instanceof IllegalArgumentException) {
        //handle this
    } else if(e instanceof SomeOtherTypeOfException) {
        //handle this
    }
}

我猜你可以在Crockford的实现中包含一个type属性,然后检查它而不是使用instanceof。从执行效果上来说,这两种方法是否有优劣之分呢?


3
对于习惯于使用Java风格异常的人来说,第二种形式更加熟悉。 - NullUserException
1
是的,出于这个原因,我更倾向于第二个。 :) - Vivin Paliath
4
我支持第二个选项,因为它在代码的纯洁性方面更具可重复利用性。确切地说,如果我要在多个地方抛出相同的异常类型,采用第一种方法会使我的代码变得混乱(庞大)。 - bellpeace
@bellpeace 很好的观点。我喜欢它提供的封装优势。确实,我在几个地方抛出异常,第一种方法开始变得难以控制。如果您将其发布为答案,我可以接受它。 - Vivin Paliath
这个回答解决了你的问题吗?如何在JavaScript中扩展Error对象? - rene
2个回答

27

2022年更新

如果您的环境支持ES6,则应该从Error类继承,如Mozilla所推荐

class IllegalArgumentException extends Error {
   // ...
}

这也是在JavaScript中扩展Error的好方法中最受欢迎的答案。


ES6以前(原始回答)

在ES6之前的环境中,已经提供了Error类作为异常的基础。它已经允许您定义消息,但也提供了一个有用的堆栈属性来跟踪异常的上下文。 您可以使用原型继承创建自己的异常类型。已经有几个stackoverflow讨论(例如:这里),介绍如何正确地实现。但是,在我找到正确和现代的方法之前,我不得不挖掘一些信息。请注意,Mozilla文档中建议使用的方法并不受stackoverflow社区的喜爱。经过大量阅读,我总结出了从Error.prototype继承的方法:

function IllegalArgumentException(sMessage) {
    this.name = "IllegalArgumentException";
    this.message = sMessage;
    this.stack = (new Error()).stack;
}
IllegalArgumentException.prototype = Object.create(Error.prototype);
IllegalArgumentException.prototype.constructor = IllegalArgumentException;

这个版本在 Node v16 和 chaijs 中的 .throw / .throws 断言中仍然能够正常工作。 - Leo Orientis

4

我支持第二种方法,因为从代码纯度的角度来看,它更具可重用性。确切地说,如果我要在多个地方抛出相同的异常(即使是不同消息的相同异常类型),使用第一种方法会让我的代码变得混乱(庞大)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接