提问人:Jayapal Chandran 提问时间:2/6/2012 最后编辑:Sebastian SimonJayapal Chandran 更新时间:11/20/2023 访问量:520373
'throw new Error' 和 'throw someObject' 有什么区别?
What is the difference between `throw new Error` and `throw someObject`?
问:
我想编写一个常见的错误处理程序,它将捕获在任何代码实例中故意抛出的自定义错误。
当我在以下代码中确实喜欢时throw new Error('sample')
try {
throw new Error({'hehe':'haha'});
// throw new Error('hehe');
} catch(e) {
alert(e);
console.log(e);
}
日志在Firefox中显示为,我无法解析该对象。Error: [object Object]
对于第二个,日志显示为:throw
Error: hehe
而当我这样做时
try {
throw ({'hehe':'haha'});
} catch(e) {
alert(e);
console.log(e);
}
控制台显示为:,我能够在其中访问错误属性。Object { hehe="haha"}
有何不同?
区别是否如代码所示?就像字符串一样,字符串将作为字符串传递,对象作为对象传递,但语法会有所不同?
我还没有探索过抛出错误对象......我只做过扔绳子。
除了上述两种方法之外,还有其他方法吗?
答:
javascript 中的“throw new Error”和“throw someObject”之间的区别在于,throw new Error 将传递给它的错误包装成以下格式 −
{ name: 'Error', message: '你在构造函数中传递的字符串' }
throw someObject 将按原样抛出对象,并且不允许从 try 块执行任何进一步的代码,即与 throw new Error 相同。
这里有一个很好的解释 The 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 种错误之一发生,还可以显式抛出自己的异常以强制按需发生异常。这对于创建您自己的错误定义以及何时应将控制权转移到捕获非常有用。
评论
Error
throw
throw "grandmother down the stairs";
Error
下面的文章可能会更详细地说明哪个是更好的选择; 或:throw 'An error'
throw new Error('An error')
http://www.nczonline.net/blog/2009/03/10/the-art-of-throwing-javascript-errors-part-2/
这表明后者()更可靠,因为Internet Explorer和Safari(不确定版本)等浏览器在使用前者时无法正确报告消息。new Error()
这样做会导致引发错误,但并非所有浏览器都能按照您预期的方式响应。Firefox、Opera 和 Chrome 都会显示一条“未捕获的异常”消息,然后包含消息字符串。Safari 和 Internet Explorer 只是抛出“未捕获的异常”错误,根本不提供消息字符串。显然,从调试的角度来看,这是次优的。
评论
throw new Error()
您首先提到以下代码:
throw new Error('sample')
然后在你的第一个例子中,你写:
throw new Error({'hehe':'haha'})
第一个 Error 对象实际上很有用,因为它需要一个字符串值,在本例中为“sample”。第二个不会,因为您正在尝试传入一个对象,并且它需要一个字符串,并且不会显示有用的错误。
错误对象将具有“message”属性,即“sample”。
评论
toString()
[object Object]
抛出“我是邪恶的”
throw
将在捕获错误时终止进一步的执行并公开消息字符串。
try {
throw "I'm Evil"
console.log("You'll never reach to me", 123465)
} catch (e) {
console.log(e); // I'm Evil
}
投掷后的控制台将永远不会因终止而到达。
throw new Error(“我是邪恶的”)
throw new Error
公开一个包含两个参数 name 和 message 的错误事件。它还终止了进一步的执行
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
}
throw Error(“我是邪恶的”)
为了完整起见,这也有效,尽管从技术上讲这不是正确的方法——
try {
throw 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
}
console.log(typeof(new Error("hello"))) // object
console.log(typeof(Error)) // function
评论
Used as a function
throw Error
throw new Error
throw
new Something()
您可以作为对象throw
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
TLDR:它们是等价的。Error(x) === new Error(x)
// 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!');
来源: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
throw
并且在功能上是等效的。但是,当您捕获它们并将它们序列化时,它们的序列化方式并不完全相同:throw Error
console.log
throw 'Parameter is not a number!';
throw new Error('Parameter is not a number!');
throw Error('Parameter is not a number!');
Console.log(e)
以上将产生 2 种不同的结果:
Parameter is not a number!
Error: Parameter is not a number!
Error: Parameter is not a number!
评论
throw 'message'
构造函数用于创建错误对象。发生运行时错误时,将引发错误对象。Error 对象还可以用作用户定义的异常的基对象。Error
用户定义的错误是通过语句抛出的。程序控制将传递给调用堆栈中的第一个块。throw
catch
在有和没有 Error 对象的情况下抛出错误之间的区别:
throw {'hehe':'haha'};
在 chrome devtools 中,如下所示:
Chrome告诉我们,我们有一个未捕获的错误,它只是一个JS对象。对象本身可能有关于错误的信息,但我们仍然不能立即知道它来自哪里。当我们处理代码并调试它时,不是很有用。
throw new Error({'hehe':'haha'});
在 chrome devtools 中,如下所示:
当我们展开 Error 对象时,它引发的错误会为我们提供堆栈跟踪。这为我们提供了错误确切来源的宝贵信息,这在调试代码时通常是有价值的信息。进一步注意,错误说 ,这是因为构造函数需要消息字符串作为第一个参数。当它收到一个对象时,它会强制它变成一个字符串。[object Object]
Error
评论
反应行为
除了其他答案之外,我还想展示 React 的一个区别。
如果我抛出一个并且我处于开发模式,我将得到一个错误屏幕和一个控制台日志。如果我抛出一个字符串文字,如果我不看控制台日志,我只会在控制台中看到它,并且可能会错过它。new Error()
例
抛出错误会记录到控制台中,并在开发模式下显示错误屏幕(该屏幕在生产中不可见)。
throw new Error("The application could not authenticate.");
而以下代码仅登录控制台:
throw "The application could not authenticate.";
throw something
适用于对象和字符串。但它比其他方法更不受支持。只能使用字符串,并将对象在 catch 块中变成无用的 [Object obj]。throw new Error("")
这已经很老了,但希望任何搜索它的人仍然可以从中学习:
首先,在 javascript 中,我们有一个叫做 Primitive Wrapper 的东西;原始包装器采用原始数据,并通过简单地使用“构造函数模式”以对象格式表示它。尽管如此,在原始包装器中,您可以决定将数据作为对象类型返回,也可以将其作为原始类型返回(在这种情况下,您现在将获得 javascript 的 go-ahead 命令来提取原始值,在这种情况下,您不使用 new 关键字)。
综上所述:
throw “My error”:这将创建一个 Error 对象并返回从构造函数“this”对象中提取的原始数据。如果你尝试检查 catch 块中的 typeof,它会告诉你这是一个原始类型的“字符串”
throw new Error(“My error”):这将返回一个对象,您可以在其中从 message 属性访问错误值。这里简单地说,“new 关键字”构造了一个“this”对象,并为其分配“{name:”Error“,message:”...“}”并返回它。当您尝试从 catch 块中检查 typeof 时,您将看到一个类型的“对象”。
注意:在将自定义对象显式传递给 throw 的情况下,它的行为就像您使用 new 关键字调用构造函数一样,因此,catch 块将返回自定义对象,而不是消息属性值。例如:throw {name:“RangeError”,message:“range is out of scope”,environment:“Occurred in testing function”}。
总之,使用任何适合你的东西,你知道你在做什么。但对我来说,如果我不需要太多数据而只是错误,那么我会选择原始返回器。
顶级域名
throw new Error('problem')
捕获发生错误的位置的多个属性。
throw 'problem'
不
new Error('message')
捕获执行堆栈 + 其他
使用 Error 对象允许您在抛出错误时捕获执行堆栈。因此,当错误被传递到错误处理树时,这个堆栈快照也会传递。
因此,在我的代码库中插入某处会导致:throw "test error"
而结果是:throw new Error('test error')
您可以看到,本机 Error 对象在我抛出错误时捕获堆栈,并使其可用于捕获错误的任何内容。这使我在调试问题时更容易跟踪问题。
除此之外,它还捕获 fileName
、lineNumber 和 columnNumber
等属性。
如果您使用堆栈跟踪,则异常跟踪器会为您记录它
在这种情况下,堆栈被打印到浏览器控制台中,但如果您使用的是 Javascript 错误日志记录工具,如 Appsignal 或 Bugsnag,那么该堆栈也将在其中可用。如果检查错误对象,则可以直接访问堆栈快照:
err = new Error('test')
err.stack
我用来决定使用哪种格式的启发式方法
当我不打算捕获异常时,我使用new Error('problem')
当我因为应用程序中发生意外或越界而引发错误时,假设本地数据存储已损坏,我可能处于不想处理它的情况,但我确实想标记它。在本例中,我将使用 Error 对象,以便获得该堆栈快照。
通过使用它,可以更轻松地追溯到发生的事情。throw new Error('Datastore is corrupted')
当我计划捕获异常时,我使用throw 'problem'
编辑 - 在重新阅读本文时,我认为下一部分需要谨慎。通常,最好非常具体地说明您选择捕获哪个错误,否则您最终可能会捕获您真正想要一直冒泡的东西。通常,最好创建特定的错误类型并捕获该特定错误(或消息字符串)。这样一来,你意想不到的错误就会浮出水面。
如果错误是我计划捕获和处理的预期错误,那么我不会从堆栈快照中获得太多用处。
因此,假设我使用一个 http 服务,它返回一个 500 HTTP 代码。我可能会将其视为一个错误,然后随后捕获并处理。throw "responseCode=500"
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');
评论
Error
的自定义错误。然后,您可以轻松地从这些扩展以获得更多粒度级别,并用于轻松检查错误(特定错误或错误类别)。instanceof Error
instanceof
该类包括调试信息(如错误的调用堆栈)作为其实例的属性。JS 解释器知道如何将实例序列化为信息丰富的错误消息字符串,并且其结构也可以由调试软件(例如浏览器开发工具)使用,以构建更丰富的错误 GUI 表示形式。这就是为什么抛出类的实例通常比简单地抛出更有用的原因,例如,抛出描述错误的字符串或表示错误代码的数字。Error
Error
Error
使用自定义错误
创建自己的子类特别有用,它允许您使用描述性名称和机器可读的名称唯一标识不同类型的错误。Error
- 调试线索,
- 用于更好地显示面向用户的错误消息的信息,或者
- 有助于从错误中恢复的信息。
然后,在处理错误时,可以使用漂亮干净的运算符来检查发生了哪种错误。例如:instanceof
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
}
}
new Error()
与Error()
有一种“方便”的速记方法可以创建 : 的实例,方法是调用 ,而不是像创建普通类的实例那样。这是语言设计者故意插入的规则例外。其他语言类也有类似的简写,例如 和 。它们还允许您调用这些类,就好像它们是函数而不是类一样。JS 不允许普通类这样做,即使它们实际上都是“类”语法糖下的函数。在 REPL 中尝试:Error
Error(message)
new Error(message)
Number()
String()
()
> 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
对设计的更广泛意见:就我个人而言,我认为这个设计决策是一个错误,因为它为 JavaScript 规则增加了更多的例外——这意味着程序员需要学习更多,语言翻译/口译员需要考虑更多。而不是C++ / Java的关键字,简单地调用一个类,就好像它是一个函数(如)应该具有关键字当前具有的属性:应该执行类的函数。在该函数中,应绑定到实例,然后隐式返回。然后,可以从语言中丢弃该关键字。这就是 Python 语法的工作方式,它更简单、更易读、更方便。new
Number("abc123")
new
constructor
this
new
评论
new Error
Error
下一个:如何使用“if”语句检查退出状态
评论
错误
screates and initializes a new Error object when called as a function rather than as a constructor. Thus the function call Error(…) is equivalent to the object creation expression new Error(…) with the same arguments.