ChatGPT解决这个技术问题 Extra ChatGPT

What is the difference between `throw new Error` and `throw someObject`?

I want to write a common error handler which will catch custom errors thrown on purpose at any instance of the code.

When I did throw new Error('sample') like in the following code

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

Log shows in Firefox as Error: [object Object] and I couldn’t parse the object.

For the second throw the log shows as: Error: hehe

Whereas when I did

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

the console showed as: Object { hehe="haha"} in which I was able to access the error properties.

What is the difference?

Is the difference as seen in the code? Like string will be just passed as string and object as objects but the syntax will be different?

I haven’t explored throwing error object… I had done only throwing strings.

Is there any other way than the above two mentioned methods?

The problem with throw new Error({prop:val}) is that's not a valid construction of Error. Error has known properties as discussed by Hemant.
based on ecma262 they both are the same: creates 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. Spec in tc39.es/ecma262/#sec-error-constructor

H
Hemant Metalia

The difference between 'throw new Error' and 'throw someObject' in javascript is that throw new Error wraps the error passed to it in the following format −

{ name: 'Error', message: 'String you pass in the constructor' }

The throw someObject will throw the object as is and will not allow any further code execution from the try block, ie same as throw new Error.

Here is a good explanation about The Error object and throwing your own errors

The Error Object

Just what we can extract from it in an event of an error? The Error object in all browsers support the following two properties:

name: The name of the error, or more specifically, the name of the constructor function the error belongs to.

message: A description of the error, with this description varying depending on the browser.

Six possible values can be returned by the name property, which as mentioned correspond to the names of the error's constructors. They are:

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()).

Throwing your own errors (exceptions)

Instead of waiting for one of the 6 types of errors to occur before control is automatically transferred from the try block to the catch block, you can also explicitly throw your own exceptions to force that to happen on demand. This is great for creating your own definitions of what an error is and when control should be transferred to catch.


oh yes. this is one good stuff i missed before asking this question. anyway the users searching for information related to this will get cleared. Now i am clear of what is what. :) Thank you. i will be back to vote in a few days.
Does not even answer the question yet the most upvoted answer?
@user9993 User ho asked question was looking for detailed understanding as per chat at that time, so accordingly answer has been provided and useful to the user. that is the reason for accepted and most up votes.
@HemantMetalia But he's right, the answer shows not even the slightest attempt to answer OPs question as stated. If some very different answer in chat was answered that should remain in chat, here question and answer have no logical connection whatsoever.
And to answer the original question, it does not matter to Javascript. However, Error (and subclasses) are used by convention. They also by default provide a stack property, although that could manually be added to any other. So it's really mostly convention, program flow is not impacted by what you throw, just that you throw at all matters. You could throw "grandmother down the stairs"; and it would work the same, except that there won't be an attached stack trace and error handling functions, reporters, debuggers expect Error, or the properties that comes with, to be more precise.
B
Brian Burns

throw "I'm Evil"

throw will terminate the further execution & expose message string on catch the error.

try { throw "I'm Evil" console.log("You'll never reach to me", 123465) } catch (e) { console.log(e); // I'm Evil }

Console after throw will never be reached cause of termination.

throw new Error("I'm Evil")

throw new Error exposes an error event with two params name & message. It also terminate further execution

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("I'm Evil")

And just for completeness, this works also, though is not technically the correct way to do it -

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


what about the diff between "throw Error('whatever')" and "throw new Error('whatever')" - both work.
Error is functional, new Error is a constructor. both works same developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
@NishchitDhanani I find it strange that such an indecipherable and wrong comment gets upvotes. Both "Error is functional", nor "new Error is a constructor" make no sense at all and/or are wrong. In that context it is unclear what exactly the link is supposed to "prove". It's the MDN page for Error, okay, where is the connection to the comment?
Okay, I got it. It's a function.
@Mörre what are you talking about?? Both of those quotes, "throw Error is functional" and "throw new Error is a constructor" is both factually accurate and makes clear sense. That is literally the only relevant difference between the two. throw just throws something, it doesn't care what, could be a string, an object, an instance of a class (new Something()). This answer got a lot of upvotes because it's the only correct answer.
E
Ed .

The following article perhaps goes into some more detail as to which is a better choice; throw 'An error' or throw new Error('An error'):

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

It suggests that the latter (new Error()) is more reliable, since browsers like Internet Explorer and Safari (unsure of versions) don't correctly report the message when using the former.

Doing so will cause an error to be thrown, but not all browsers respond the way you’d expect. Firefox, Opera, and Chrome each display an “uncaught exception” message and then include the message string. Safari and Internet Explorer simply throw an “uncaught exception” error and don’t provide the message string at all. Clearly, this is suboptimal from a debugging point of view.


And what if I'm writing code in ExpressJS for a REST API, this issue with browsers would not exist anymore. Is it nevertheless preferable to use throw new Error() ?
P
Penny Liu

TLDR: they are equivalent 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!');

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

throw and throw Error are functionally equivalent. But when you catch them and serialize them to console.log they are not serialized exactly the same way:

throw 'Parameter is not a number!';
throw new Error('Parameter is not a number!');
throw Error('Parameter is not a number!');

Console.log(e) of the above will produce 2 different results:

Parameter is not a number!
Error: Parameter is not a number!
Error: Parameter is not a number!

What about this : throw 'message' is it the same ?
"throw and throw Error will are functionally equivalent" – not really. One throws a string, which things like Bugsnag will complain about because it can't get a stacktrace from them. Do you mean functionally as in it'll stop the code running, or that it'll throw something? Either way they're semantically different?
I
IonicBurger

You first mention this code:

throw new Error('sample')

and then in your first example you write:

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

The first Error object would actually be useful, because it is expecting a string value, in this case 'sample'. The second would not because you are trying to pass an object in, and it is expecting a string, and would not display a helpful error.

The error object would have the "message" property, which would be 'sample'.


The second one does work, just not in a very useful way. It executes the toString() method on the object passed in, resulting in [object Object] in the error (as the Op wrote).
W
Willem van der Veen

The Error constructor is used to create an error object. Error objects are thrown when runtime errors occur. The Error object can also be used as a base object for user-defined exceptions.

User-defined Errors are thrown via the throw statement. program control will be passed to the first catch block in the call stack.

The difference between throwing an error with and without Error object:

throw {'hehe':'haha'};

In chrome devtools looks like this:

https://i.stack.imgur.com/6KJ40.png

Chrome tells us that we have an uncaught error which just is a JS object. The object itself could have information regarding the error but we still don't know immediately where it came from. Not very useful when we are working on our code and debugging it.

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

In chrome devtools looks like this:

https://i.stack.imgur.com/687rC.png

An error thrown with the Error object gives us a stack trace when we expand it. This gives us valuable information where the error precisely came from which is often valuable information when debugging your code. Further note that the error says [object Object], this is because the Error constructor expects a message string as a first argument. When it receives a object it will coerce it into a string.


this answer makes the most sense
L
Lucas Dolsan

you can throw as object

throw ({message: 'This Failed'})

then for example in your try/catch

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

or just throw a string error

throw ('Your error')

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

throw new Error //only accept a string

P
Peter Nixey

TLDR

throw new Error('problem') captures a number of properties of the place where the error happened.

throw 'problem' does not

new Error('message') captures the execution stack + others

Using an Error object allows you to capture the execution stack at the point where you throw the error. So when the error gets passed up the error handling tree, so does this stack snapshot.

So inserting throw "test error" somewhere in my codebase results in:

https://i.stack.imgur.com/TO2Ff.png

Whereas throw new Error('test error') results in:

https://i.stack.imgur.com/I3P2A.png

You can see that the native Error object captures the stack at the point I throw the error and makes it available to whatever captures the error. That makes it easier for me to trace the problem when I'm debugging it.

In addition to that it also captures properties such as fileName, lineNumber and columnNumber.

If you use the stack trace it's there for exception trackers to log for you

In this case the stack is being printed into the browser console but if you're using Javascript error logging tools like Appsignal or Bugsnag then that stack will also be available in them too. If you inspect the error object you can access the stack snapshot directly:

err = new Error('test')
err.stack

https://i.stack.imgur.com/MwD7U.png

The heuristic I use for deciding which format to use

When I don't plan to catch the exception I use new Error('problem')

When I'm throwing an error because something unexpected or out-of-bounds has happened in the application, let's say the local datastore is corrupted, I might be in a situation where I don't want to handle it, but I do want to flag it. In this case I'll use the Error object so I have that stack snapshot.

By using throw new Error('Datastore is corrupted') it's easier to trace my way back to what's happened.

When I plan to catch the exception I use throw 'problem'

Edit - on re-reading this I think the next part needs some caution. It's generally a good idea to be very specific about which error you choose to catch otherwise you can end up catching things that you really wanted to bubble all the way up. In general it's probably better to create a specific error type and catch that specific error (or message string). This allows errors you didn't anticipate to bubble up to the surface."

If the error is an expected error that I plan to catch and handle then I'm not going to get much use out of the stack snapshot.

So, let's say I use an http service and it returns a 500 HTTP code. I may treat this as an error which I throw "responseCode=500" and then subsequently catch and handle.


C
Community

React behavior

Apart from the rest of the answers, I would like to show one difference in React.

If I throw a new Error() and I am in development mode, I will get an error screen and a console log. If I throw a string literal, I will only see it in the console and possibly miss it, if I am not watching the console log.

Example

Throwing an error logs into the console and shows an error screen while in development mode (the screen won't be visible in production).

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

https://i.stack.imgur.com/0EF3P.png

Whereas the following code only logs into the console:

throw "The application could not authenticate.";

E
Emmanuel Onah

This is quite old but hopefully, anyone searching this can still learn from this:

First and famous, in javascript, we have something called Primitive Wrapper; a primitive wrapper takes primitive data and represents it in an object format by simply using the "constructor pattern". Still yet, in primitive wrappers, you can decide to have your data returned as an object type or you can have it returned as its primitive type(in this situation, you are now given a go-ahead command for javascript to extract the primitive value and in this case, you don't use the new keyword).

In Summary:

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".

Note: in a situation where you explicitly pass in a custom object to the throw, it will behave as if you invoked the constructor using the new keyword and therefore, the catch block will return you the custom object and not the message property value. For example: throw {name:"RangeError",message:"range is out of scope",environment:"Happened in testing function"}.

In conclusion, use whatever suits you ones you know what you are doing. But for me if i don't need much data but rather just the error, then I go for Primitive returner.


S
Steve Moretz

throw something works with both object and strings.But it is less supported than the other method.throw new Error("") Will only work with strings and turns objects into useless [Object obj] in the catch block.


b
buddemat

throw new Error() is good for throwing a specified error. But if you want to do custom error handling, it's better to use throw { example: 'error' } .

That is, if you want to know the specified error, use throw new Error("example string") , if you want to handle the error in custom, use 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');

Throwing something that isn't instanceof Error isn't a great idea and complicates the rest of the code because now you can't rely on the normal error properties being available, also you can't trace your error back to its source because it has no stack. While the second example is okay, it's better to use custom errors that inherit from Error. You can then easily extend from those for more levels of granularity, and use instanceof to check for errors (either a specific one or a class of errors) easily.
I use custom errors by inheriting errors for network errors like api errors, db errors. As you said, custom errors are useful when debugging. However, if there is no file necessary to start the server or a port conflict error occurs, I think it is right to stop the server with its own error rather than a custom error.