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

当我抛出新的错误('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"},我可以在其中访问错误属性。

有什么不同?

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

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

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


当前回答

你首先提到了这段代码:

throw new Error('sample')

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

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

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

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

其他回答

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('sample')

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

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

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

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

投掷“我是邪恶的”

Throw将终止进一步的执行并在捕获错误时暴露消息字符串。

尝试{ 投掷“我是邪恶的” console.log("你永远也找不到我",123465) } catch (e) { console.log (e);//我是邪恶的 }

抛出后将永远无法到达控制台,导致终止。


抛出新的错误("I'm Evil")

暴露一个带有两个参数名称和消息的错误事件。它还会终止进一步的执行

尝试{ 抛出新的错误("I'm Evil") console.log("你永远也找不到我",123465) } catch (e) { console.log (e.name e.message);//错误I'm Evil }

抛出错误("I'm Evil")

为了完整起见,这个也可以,虽然技术上不是正确的方法

尝试{ 抛出错误("I'm Evil") console.log("你永远也找不到我",123465) } catch (e) { console.log (e.name e.message);//错误I'm Evil } console.log(typeof(新的错误("hello"))) //对象 console.log(typeof(Error)) //函数

你可以把它作为对象抛出

throw ({message: 'This Failed'})

例如在try/catch中

try {
//
} catch(e) {
    console.log(e); //{message: 'This Failed'}
    console.log(e.message); //This Failed
}

或者只是抛出一个字符串错误

throw ('Your error')

try {
//
} catch(e) {
    console.log(e); //Your error
}

throw new Error //only accept a string

Error构造函数用于创建错误对象。发生运行时错误时抛出错误对象。Error对象还可以用作用户定义异常的基对象。

用户定义错误通过throw语句抛出。程序控制将被传递给调用堆栈中的第一个catch块。

有和没有error对象时抛出错误的区别:


throw {'hehe':'haha'};

在chrome中,devtools是这样的:

Chrome告诉我们,我们有一个未捕获的错误,这只是一个JS对象。对象本身可能有关于错误的信息,但我们仍然不知道它来自哪里。在我们处理代码和调试它的时候,这不是很有用。


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

在chrome中,devtools是这样的:

与error对象一起抛出的错误在展开堆栈时提供堆栈跟踪。这为我们提供了有价值的信息,错误准确地来自哪里,这在调试代码时通常是有价值的信息。进一步注意,错误说的是[object object],这是因为error构造函数期望一个消息字符串作为第一个参数。当它接收到一个对象时,它会将其强制转换为一个字符串。