我想编写一个通用的错误处理程序,它将捕获在代码的任何实例中故意抛出的自定义错误。

当我抛出新的错误('sample'),如下所示

try {
    throw new Error({'hehe':'haha'});
    // throw new Error('hehe');
} catch(e) {
    alert(e);
    console.log(e);
}

日志在Firefox中显示为错误:[object object],我无法解析该对象。

对于第二次抛出,日志显示为:错误:呵呵

然而当我这样做的时候

try {
    throw ({'hehe':'haha'});
} catch(e) {
    alert(e);
    console.log(e);
}

控制台显示为:对象{hehe="haha"},我可以在其中访问错误属性。

有什么不同?

区别是否如代码中所示?比如字符串会作为字符串传递而对象作为对象但语法会有所不同?

我还没有探索过抛出错误对象…我只抛出了字符串。

除了以上两种方法,还有别的办法吗?


当前回答

的反应行为

除了其他的答案,我还想说明React的一个不同之处。

如果我抛出一个新的Error(),并且我处于开发模式,我将得到一个错误屏幕和一个控制台日志。如果我抛出一个字符串字面量,我只会在控制台中看到它,如果我没有观察控制台日志,可能会错过它。

例子

在开发模式下向控制台抛出错误日志并显示错误屏幕(在生产环境中不可见)。

throw new Error("The application could not authenticate.");

而下面的代码只能登录到控制台:

throw "The application could not authenticate.";

其他回答

The Error class includes debugging information (as properties of its instances), such as the error's call stack. JS interpreters know how to serialise those properties into an informative error message string, and they can also be consumed by debugging software - such as browser dev tools - to construct a more informative GUI representation of the error. This is why it's generally more useful to throw an instance of the Error class rather than simply throwing, for example, a string describing the error, or a number representing an error code.

使用自定义错误

特别有用的是创建自己的Error子类,它允许您使用描述性名称和机器可读的惟一标识不同类型的错误……

调试线索, 信息,以便更好地面向用户的错误消息,或者 帮助从错误中恢复的信息。

然后,在处理错误时,可以使用简洁的instanceof操作符来检查发生了什么类型的错误。例如:

class ShoesTooBig extends Error {}

class DangerousWaterCurrent extends Error {
    constructor(waterSpeed){
        super(`These waters are moving at ${waterSpeed} metres per second - too fast to cross!`) // Provide a `message` argument to the Error() constructor
        this.waterSpeed = waterSpeed // This passes some context about why/how the error occurred back to whichever function is going to catch & handle it
    }
}

// ...later...

try {
    swimAcrossRiver(footwear, river)
} catch (thrownValue) {
    if (thrownValue instanceof DangerousWaterCurrent) {
        constructDam(river, thrownValue.waterSpeed)
    } else {
        throw thrownValue // "Re-throw" the error back up the execution chain, for someone else to handle
    }
}

new Error() vs Error()

There is a "convenient" shorthand way to make an instance of Error: by calling Error(message), instead of new Error(message), the way you'd make an instance of a normal class. This is a deliberate exception, inserted by the language designers, to the rule. There are similar shorthands for other in-language classes, like Number() and String(). They also let you call these classes with () as if they were functions, not classes. JS doesn't allow normal classes to do this, even though they're all actually functions under the syntactical sugar of "classes". Try in a REPL:

> class E extends Error {}
undefined
> Error(); 'a value'
"a value"
> E(); 'a value'
Uncaught TypeError: Class constructor E cannot be invoked without 'new'
    at <anonymous>:2:1

就我个人而言,我认为这个决定是错误的,因为它为JavaScript规则添加了更多的例外。而不是c++ /Java的new关键字,简单地调用一个类,就好像它是一个函数(如在Number("abc123")))应该执行类的构造函数,并将其绑定到实例,就像通常发生的new关键字一样(这是Python的语法工作方式,它最终更易于阅读和方便)。

throw new Error()用于抛出指定的错误。但如果你想做自定义错误处理,最好使用throw {example: 'error'}。

也就是说,如果你想知道指定的错误,使用throw new error ("example string"),如果你想自定义处理错误,使用throw。


function makeErrorResponse(err = {}, httpStatus, status, message, message) {
    const error = new Error();

    error.httpStatus = httpStatus;
    error.status = status;
    error.message = message;
    error.err = err;

    return error;
  }

throw makeErrorResponse({}, 500, 500, 'server error');

你首先提到了这段代码:

throw new Error('sample')

然后在你的第一个例子中你写:

throw new Error({'hehe':'haha'}) 

第一个Error对象实际上是有用的,因为它需要一个字符串值,在本例中是'sample'。第二个则不会,因为您正在试图传递一个对象,并且它期待一个字符串,并且不会显示有用的错误。

错误对象将具有“message”属性,即“sample”。

这是相当古老的,但希望任何搜索它的人仍然可以从中学到东西:

首先,在javascript中,我们有一个叫做原始包装器的东西;原语包装器接受原语数据,并通过简单地使用“构造函数模式”以对象格式表示它。不过,在原语包装器中,您可以决定将数据作为对象类型返回,也可以将其作为原语类型返回(在这种情况下,您现在得到了一个让javascript提取原语值的go-ahead命令,在这种情况下,您不使用new关键字)。

总而言之:

throw "My error": this creates an Error object and returns the primitive data extracted from the constructor "this" object. And if you try checking the typeof in the catch block, it tells you its a primitive typeof "string" throw new Error("My error"): this returns you an object where you can access the error value from the message property. What simply happens here is that the "new keyword" constructs a "this" object and assign "{name:"Error",message:"..."}" to it and returns it. And when you try to check the typeof from the catch block, you will see a typeof "object".

注意:在显式地将自定义对象传递给throw的情况下,它的行为就像使用new关键字调用构造函数一样,因此,catch块将返回自定义对象而不是消息属性值。例如:throw {name:"RangeError",message:"range is out of scope",environment:" occurred in testing function"}。

总之,使用任何适合你的东西,你知道你在做什么。但对于我来说,如果我不需要太多的数据,而只是需要错误,那么我就使用原始返回器。

'throw new Error'和'throw someObject'在javascript中的区别在于,throw new Error将传递给它的错误以以下格式包装

{name: '错误',消息:'传入构造函数的字符串' }

throw someObject将按原样抛出对象,并且不允许从try块执行任何进一步的代码,即与throw new Error相同。

下面是关于Error对象和抛出自己的错误的一个很好的解释

错误对象

在发生错误时,我们能从中提取什么?所有浏览器中的Error对象都支持以下两个属性:

name:错误的名称,或者更具体地说,错误所属的构造函数的名称。 message:错误的描述,该描述因浏览器而异。

name属性可以返回六个可能的值,如前所述,它对应于错误构造函数的名称。它们是:

Error Name          Description

EvalError           An error in the eval() function has occurred.

RangeError          Out of range number value has occurred.

ReferenceError      An illegal reference has occurred.

SyntaxError         A syntax error within code inside the eval() function has occurred.
                    All other syntax errors are not caught by try/catch/finally, and will
                    trigger the default browser error message associated with the error. 
                    To catch actual syntax errors, you may use the onerror event.

TypeError           An error in the expected variable type has occurred.

URIError            An error when encoding or decoding the URI has occurred 
                   (ie: when calling encodeURI()).

抛出自己的错误(异常)

在控制自动从try块转移到catch块之前,您不必等待6种类型错误中的一种发生,还可以显式地抛出自己的异常,以强制按需发生这种情况。这对于创建关于错误是什么以及何时应该将控制转移到catch的定义非常有用。