Use coffeescript/javascript 'throw error' or 'throw new Error(error)'?

13,429

Same as in other languages like C# or Java:

  • throw error throws the same Error object
  • throw new Error(error) wraps it into a new Error object. The later is used, for example, in Java when you need to convert checked Exception into unchecked one. In JavaScript you don't need to wrap exceptions as this would make stacktrace a bit longer and less pretty.

Edit: There're some security implications as well. Here's an example:

function noWrap() {
    try {
        var o = {}; o.nonexistingMethod();
    } catch (error) {
        throw error;
    }
}

function wrap() {
    try {
        var o = {}; o.nonexistingMethod();
    } catch (error) {
        throw new Error(error);
    }
}

Calling noWrap() produces the following error message:

"TypeError: Object #<Object> has no method 'nonexistingMethod'"
// with error.arguments === ['nonexistingMethod', o]

Calling wrap() produces the following error message:

"Error: TypeError: Object #<Object> has no method 'nonexistingMethod'"
//  with error.arguments === undefined

So, as you can see by using a wrapping Error object we can hide the arguments of original error. Suppose you're writing one of the following:

  • some kind of a library
  • a script which will be loaded on a page that you don't own (for example, some kind of like or tweet button)
  • a script on a page that has some third-party scripts loaded (social buttons, ads, tracking code, etc.)

In all those cases listed above in order to stay secure you should wrap your Error objects. Otherwise you may accidentally leak references to your internal objects, functions and variables.

Edit 2: Regarding stacktraces. Both variants preserve them. Here's a working example and I get the following stacktraces in Chrome:

// No wrapping:
TypeError: Object #<Object> has no method 'nonexistingMethod'
    at noWrap (http://fiddle.jshell.net/listochkin/tJzCF/show/:22:23)
    at http://fiddle.jshell.net/listochkin/tJzCF/show/:37:5
    at http://fiddle.jshell.net/js/lib/mootools-core-1.4.5-nocompat.js:3901:62
    at http://fiddle.jshell.net/js/lib/mootools-core-1.4.5-nocompat.js:3915:20

// Wrapping:
Error: TypeError: Object #<Object> has no method 'nonexistingMethod'
    at wrap (http://fiddle.jshell.net/listochkin/tJzCF/show/:32:15)
    at http://fiddle.jshell.net/listochkin/tJzCF/show/:44:5
    at http://fiddle.jshell.net/js/lib/mootools-core-1.4.5-nocompat.js:3901:62
    at http://fiddle.jshell.net/js/lib/mootools-core-1.4.5-nocompat.js:3915:20 
Share:
13,429

Related videos on Youtube

Mihai Oprea
Author by

Mihai Oprea

I solve problems. http://blog.mihaioprea.com LinkedIn: http://ro.linkedin.com/pub/mihai-oprea/8/44a/82 Twitter: http://twitter.com/#!/mishu21

Updated on September 16, 2022

Comments

  • Mihai Oprea
    Mihai Oprea over 1 year

    I have the following coffeescript code:

    try
       do something
    catch error
       log something
       throw error
    

    Should I use throw new Error(error) instead of throw error?

    What is the difference?

  • Mihai Oprea
    Mihai Oprea almost 12 years
    Someone advised me that the wrapped version gives you an error object with a full stacktrace, otherwise you only get the error message.
  • Andrei Андрей Листочкин
    Andrei Андрей Листочкин almost 12 years
    It's browser-dependent. For example, In IE9 there's no stack property on Error objects. I don't know about other browsers.