Debugging JavaScript: Throw Away Your Alerts!

    James Edwards
    Share

    One JavaScript statement that rarely surfaces in the wild is throw(). The throw statement allows you to throw a formal error — sending details of the error to the browser’s error console — and halting further execution of the script.

    The throw statement is particularly useful for APIs developers, as a way to warn its user-developers about runtime issues, such as missing or invalid input data. Its use should be generally preferable to alert() because it makes best use of the browser’s native functionality (and it’s less annoying):

    if(typeof input == 'undefined')
    {
    	throw('Missing input');
    }
    else if(parseFloat(input) != input)
    {
    	throw('Input must be a number');
    }

    Using throw() with a string argument will throw a general error. However you can also create and pass an Error object, with which you can specify more details about the error:

    var err = new Error();
    err.name = 'My API Input Error';
    err.message = 'Input must be a number';
    throw(err);

    The example above produces this output in Opera’s error console:

    Opera's error console showing the error just detailed

    Firefox’s console doesn’t show the error name, only the message; but it’s still almost as useful:

    Firefox's error console showing the error just detailed

    The important thing to note is that anywhere you use throw() will halt the execution of the script (not just the enclosing scope). So you should arrange your code so that any throw() statement comes at the end of an execution block:

    function err(type, message)
    {
    	var err = new Error();
    	err.name = 'My API ' + type + ' Error';
    	err.message = message;
    	throw(err);
    }
    
    // the delete in this example won't happen
    if(typeof this.input == 'undefined')
    {
    	err('Input', 'Missing input');
    	delete this.input;
    }
    
    // but this delete will happen fine
    if(typeof this.input == 'undefined')
    {
    	delete this.input;
    	err('Input', 'Missing input');
    }

    Of course, a single language statement — however useful — can never replace a fully-featured debugging tool like Firebug; a proper debugger lets you set breakpoints, watchpoints, step-through execution … all kinds of goodness. Firebug even lets you log messages to its own console.

    But Firebug is a browser-specific tool, where this is a cross-browser language feature, so it can be safely integrated into the heart of a script without any chance of unsatisfied dependencies.