`throw new Error`和`throw someObject`有什么区别?

Jay*_*ran 336 javascript error-handling exception-handling object throw

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

当我throw new Error('sample')在下面的代码中做了

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

日志在Firefox中显示,Error: [object Object]我无法解析该对象.

对于第二个throw,日志显示为:Error: hehe

而当我这样做的时候

try {
    throw ({'hehe':'haha'});
} catch(e) {
    alert(e);
    console.log(e);
}
Run Code Online (Sandbox Code Playgroud)

控制台显示为:Object { hehe="haha"}其中我能够访问错误属性.

有什么不同?

是否在代码中看到了差异?像字符串一样只是作为字符串和对象传递给对象,但语法会有所不同吗?

我没有探索过抛出错误对象......我只是抛出了字符串.

还有除上述两种方法之外的其他方法吗?

Hem*_*lia 202

这里是关于The 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()).
Run Code Online (Sandbox Code Playgroud)

抛出自己的错误(例外)

在将控制从try块自动传输到catch块之前,您可以显式抛出自己的异常以强制按需发生,而不是等待6种类型的错误中的一种发生.这非常适合创建自己的错误定义,以及何时应将控制转移到catch.

  • 甚至没有回答这个问题但最受欢迎的答案呢? (118认同)
  • 哦,是的.在提出这个问题之前,这是我错过的一件好事.无论如何,搜索与此相关的信息的用户将被清除.现在我清楚什么是什么.:) 谢谢.我将在几天后回来投票. (4认同)
  • @HemantMetalia但是他是对的,答案显示出甚至没有丝毫尝试回答OP的问题。如果在聊天中回答了一些应该保留在聊天中的非常不同的答案,那么这里的问题和答案就没有逻辑联系。 (3认同)
  • @user9993 用户ho提出的问题是为了根据当时的聊天寻求详细的理解,因此已经提供了相应的答案并且对用户有用。这就是获得接受和最多赞成票的原因。 (2认同)

Nis*_*ani 83

扔"我是邪恶的"

抛出将终止进一步执行并公开消息字符串以 捕获错误.

try{
    throw 'I\'m Evil'
    console.log('You\'ll never reach to me', 123465)
}
catch(e){
    console.log(e); //I\'m Evil
}
Run Code Online (Sandbox Code Playgroud)

投掷后的控制台永远不会达到终止的原因.

抛出新的错误("我很甜蜜")

throw new Error使用两个params 名称消息公开错误事件.它还终止进一步的执行

try{
     throw new Error('I\'m Evil')
     console.log('You\'ll never reach to me', 123465)
}
catch(e){
        console.log(e.name, e.message); //Error, I\'m Evil
}
Run Code Online (Sandbox Code Playgroud)

  • @NishchitDhanani 我觉得很奇怪,这样一个难以理解和错误的评论居然得到了赞成。“Error 是函数式的”和“new Error 是构造函数”都没有任何意义和/或都是错误的。在这种情况下,尚不清楚该链接到底应该“证明”什么。这是 `Error` 的 MDN 页面,好吧,注释的连接在哪里?评论和回答OP问题的一半人应该保持沉默。 (12认同)
  • @Mörre 你在说什么?这两句话“` throw Error` 是函数式的”和““ throw new Error` 是一个构造函数”实际上都是准确的,而且意义明确。这实际上是两者之间唯一相关的区别。`throw` 只是抛出一些东西,它不关心什么,可以是一个字符串,一个对象,一个类的实例(`new Something()`)。这个答案得到了很多人的赞同,因为这是唯一正确的答案。 (9认同)
  • “ throw Error('whatever')”和“ throw new Error('whatever')”之间的区别怎么样-都可以。 (7认同)
  • 错误是有效的,新错误是构造函数.两者都相同https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error (7认同)
  • 好的,我明白了。这是一个**功能**。 (2认同)

Ed *_*d . 69

以下文章可能会更详细地说明哪个是更好的选择; throw 'An error'或者throw new Error('An error'):

http://www.nczonline.net/blog/2009/03/10/the-art-of-throwing-javascript-errors-part-2/

它表明后者(new Error())更可靠,因为Internet Explorer和Safari(不确定版本)等浏览器在使用前者时无法正确报告消息.

这样做会导致抛出错误,但并非所有浏览器都以您期望的方式响应.Firefox,Opera和Chrome均显示"未捕获的异常"消息,然后包含消息字符串.Safari和Internet Explorer只是抛出"未捕获的异常"错误,并且根本不提供消息字符串.显然,从调试的角度来看,这是次优的.


Ion*_*ger 34

你首先提到这段代码:

throw new Error('sample')
Run Code Online (Sandbox Code Playgroud)

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

throw new Error({'hehe':'haha'}) 
Run Code Online (Sandbox Code Playgroud)

第一个Error对象实际上可以工作,因为它期望一个字符串值,在本例中为'sample'.第二个不会,因为你试图传入一个对象,它期待一个字符串.

错误对象将具有"message"属性,该属性为"sample".

  • 第二个确实起作用,只是不是以非常有用的方式。它对传入的对象执行`toString()`方法,导致`[object Object]`出错(如Op所写)。 (10认同)

Wil*_*een 25

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

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

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


throw {'hehe':'haha'};
Run Code Online (Sandbox Code Playgroud)

在 chrome devtools 中看起来像这样:

在此处输入图片说明

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


throw new Error({'hehe':'haha'}); 
Run Code Online (Sandbox Code Playgroud)

在 chrome devtools 中看起来像这样:

在此处输入图片说明

当我们展开它时,Error 对象抛出的错误为我们提供了一个堆栈跟踪。这为我们提供了宝贵的信息,错误的确切来源在调试代码时通常是有价值的信息。进一步注意错误是 [object Object],这是因为Error构造函数需要一个消息字符串作为第一个参数。当它接收到一个对象时,它会将它强制转换为一个字符串。

  • 这个答案最有道理 (2认同)

Pet*_*xey 16

总长DR

throw new Error('problem')捕获错误发生位置的许多属性。

throw 'problem'才不是

new Error('message')捕获执行堆栈+其他

使用 Error 对象可以让您捕获抛出错误时的执行堆栈。因此,当错误沿着错误处理树向上传递时,该堆栈快照也会向上传递。

因此,throw "test error"在我的代码库中插入某个位置会导致:

在此输入图像描述

throw new Error('test error')结果是:

在此输入图像描述

您可以看到本机 Error 对象在我抛出错误时捕获堆栈,并使其可用于捕获错误的任何对象。这使我在调试时更容易跟踪问题。

除此之外,它还捕获fileNamelineNumber和 等columnNumber属性。

如果您使用堆栈跟踪,异常跟踪器可以为您记录日志

在这种情况下,堆栈将被打印到浏览器控制台中,但如果您使用 Appsignal 或 Bugsnag 等 Javascript 错误记录工具,那么该堆栈也将在其中可用。如果您检查错误对象,您可以直接访问堆栈快照:

err = new Error('test')
err.stack
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我用于决定使用哪种格式的启发式

当我不打算捕获异常时我使用new Error('problem')

当我因为应用程序中发生意外或越界的情况而引发错误时(假设本地数据存储已损坏),我可能会处于不想处理它的情况,但我确实想要标记它。在本例中,我将使用 Error 对象,以便获得堆栈快照。

通过使用throw new Error('Datastore is corrupted')它,我可以更轻松地追溯所发生的事情。

当我计划捕获异常时我使用throw 'problem'

编辑 - 重新阅读本文时,我认为下一部分需要谨慎。一般来说,最好明确您选择捕获的错误,否则您最终可能会捕获您真正想要一直冒泡的内容。一般来说,最好创建一个特定的错误类型并捕获该特定错误(或消息字符串)。这会让你没有预料到的错误浮出水面。”

如果错误是我计划捕获和处理的预期错误,那么我不会从堆栈快照中得到太多用处。

因此,假设我使用 http 服务,它返回 500 HTTP 代码。我可能会将其视为一个错误throw "responseCode=500",然后捕获并处理该错误。


ion*_*ono 14

该类包含调试信息(例如错误的调用堆栈)作为其实例的属性Error。JS 解释器知道如何将实例序列化为信息丰富的错误消息字符串,并且调试软件(例如浏览器开发工具)也可以使用它们的结构来构建信息更丰富的错误 GUI 表示。这就是为什么抛出类的实例通常比简单地抛出更有用,例如,描述错误的字符串或表示错误代码的数字。ErrorError

使用自定义错误

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

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

然后,当你处理错误时,你可以使用nice and cleaninstanceof运算符来检查发生了什么类型的错误。例如:

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(river)
} catch (thrownValue) {
    if (thrownValue instanceof DangerousWaterCurrent) {
        if (thrownValue.waterSpeed <= 3){ 
            paddleKayak(river)
        } else {
            constructBridge(river)
        }
    } else {
        throw thrownValue // "Re-throw" the error back up the execution chain, for someone else to handle
    }
}
Run Code Online (Sandbox Code Playgroud)

new Error()Error()

有一种“方便”的简写方法来创建 的实例Error:通过调用Error(message), 而不是new Error(message)创建普通类的实例的方式。这是语言设计者故意插入的例外规则。其他语言类也有类似的简写,例如Number()String()。它们还允许您调用这些类,就()好像它们是函数而不是类一样。JS 不允许普通类执行此操作,即使它们实际上都是“类”语法糖下的函数。在 REPL 中尝试:

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

对设计的更广泛的看法:就我个人而言,我认为这个设计决策是一个错误,因为它为 JavaScript 规则添加了更多例外 - 这意味着程序员需要学习更多内容,并且语言翻译/解释人员需要考虑更多内容。与 C++/Java 的new关键字不同,只需像函数一样调用类(如 中所示Number("abc123"))就应该具有该关键字当前具有的属性:应该执行new该类的函数。 constructor 在该函数内部,this应该绑定到实例,然后隐式返回。new然后可以从语言中丢弃该关键字。这就是Python的语法的工作原理,而且它更简单、更易读、更方便。

  • 这是充分涵盖“new Error”和“Error”之间差异的唯一答案 (5认同)

Mba*_*nda 10

你可以throw作为对象

throw ({message: 'This Failed'})
Run Code Online (Sandbox Code Playgroud)

然后例如在您的 try/catch

try {
//
} catch(e) {
    console.log(e); //{message: 'This Failed'}
    console.log(e.message); //This Failed
}
Run Code Online (Sandbox Code Playgroud)

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

throw ('Your error')

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

throw new Error //only accept a string
Run Code Online (Sandbox Code Playgroud)


Dav*_*han 8

TLDR:它们是等效的。

// this:
const x = Error('I was created using a function call!');
????// has the same functionality as this:
const y = new Error('I was constructed via the "new" keyword!');
Run Code Online (Sandbox Code Playgroud)

来源:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error

  • “ throw 和 throw Error 在功能上是等价的”——事实并非如此。一个会抛出一个字符串,Bugsnag 之类的东西会抱怨这个问题,因为它无法从中获取堆栈跟踪。您的意思是在功能上会停止代码运行,还是会抛出一些东西?不管怎样,它们在语义上是不同的? (2认同)

El *_*Mac 6

反应行为

除了其余的答案,我想展示 React 的一个不同之处。

如果我抛出 anew Error()并且我处于开发模式,我会得到一个错误屏幕和一个控制台日志。如果我抛出一个字符串文字,我只会在控制台中看到它,如果我不看控制台日志,我可能会错过它。

例子

将错误记录到控制台在开发模式下显示错误屏幕(该屏幕在生产中不可见)。

throw new Error("The application could not authenticate.");
Run Code Online (Sandbox Code Playgroud)

反应中的错误屏幕

而以下代码仅登录到控制台:

throw "The application could not authenticate.";
Run Code Online (Sandbox Code Playgroud)