RangeError, TypeError, and URIError JavaScript Error Types

JavaScript divides runtime errors into six separate error types. The benefit to us as developers is that we can more accurately pinpoint exactly what kind of error we're dealing with. In the Handling JavaScript Errors by Type article, we learned how to distinguish between different error types using the Error.name property as well as the SyntaxError, EvalError, and ReferenceError error types. Today, we'll be covering the RangeError, TypeError, and URIError types. We'll also see how to create our own error type.

The RangeError

A RangeError is thrown under a couple of circumstances. The first happens when you pass a number as an argument to a function that lies outside the range of permissible values. For instance, when creating an array with an illegal length, or when passing invalid values to the numeric methods Number.toExponential(), Number.toFixed(), or Number.toPrecision(). For the record, an array in JavaScript can have 0 to (2^32-1) elements, or 4,294,967,295. Both Number.toExponential() and Number.toFixed() accept arguments from 0 to 20, while Number.toPrecision()'s expected range is from 1 to 21 inclusive.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
var a = new Array(4294967295);  //OK
var b = new Array(-1); //range error
 
var num = 2.555555;
document.writeln(num.toExponential(4));  //OK document.writeln(num.toExponential(-2)); //range error!
 
num = 2.9999;
document.writeln(num.toFixed(2));   //OK
document.writeln(num.toFixed(25));  //range error!
 
num = 2.3456;
document.writeln(num.toPrecision(1));   //OK
document.writeln(num.toPrecision(22));  //range error!
Another, albeit lesser known cause of RangeErrors are recursive functions like the one below that end up exhausting all the available stack space. While each browser displays its own error message, Safari does clearly identify it as a RangeError:

1
2
3
4
5
6
7
var a = new Array(1);
function recurse(a){
    a[0] = new Array(1);
    recurse(a[0]);
}
 
recurse(a); //displays "RangeError: Maximum call stack size exceeded."

The TypeError

Although JavaScript does employ something called loose typing, it certainly does recognize all of the usual data types, such as numbers, strings, objects, arrays, and the JavaScript-specific "function" type. Use the wrong type for a given operation, and a TypeError will result:

1
2
3
4
var num = 234; num.substr(1,1); //uncaught exception: TypeError: num.substr is not a function
 
var p1 = document.createElement('p');
//the event handler is an inline function so the boolean value of true //is being passed to the addEventListener() method p1.addEventListener("click", function() { return true; }(), false); //Object doesn't support this property or method

The URIError

A URIError is thrown by the decodeURI(), decodeURIComponent(), encodeURI(), encodeURIComponent(), escape(), and unescape() URI handling functions when they are passed a malformed URI. Here's an example that generates a URIError while attempting to decode the string "%". This happens because the "%" character represents the beginning of a URI escape sequence. Since nothing follows the "%", the string is an invalid escape sequence:

1
2
decodeURIComponent("%");
//The URI to be decoded is not a valid encoding
Other special URI characters include:
  • Colon (:)
  • Forward Slash (/)
  • Semi-colon (;)
  • Question-mark (?)
  • Hash (#)

Throwing Your Own Errors

For handling errors in your own code, it's common practice to subclass the generic error types and create your own. To that end, here's some code that defines, throws, and handles a custom child of the RangeError object:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function MyRangeError(message) {
  this.name    = 'MyRangeError';
  this.message = message || 'A MyRangeError ocurred!';
// Inherit from the RangeError's prototype.
MyRangeError.prototype = new RangeError();
MyRangeError.prototype.constructor = MyRangeError; 
 
function setTop50ListItem(index, item) {
  if (index < 1 || index > 50) {
    throw new MyRangeError('The index has to be between 1 and 50.');
  }
  else {
    //array is zero based
    top50List[index - 1] = item;
  }
}
 
var top50List = new Array(50);
try {
  setTop50ListItem(51, 'Rob Gravelle');
} catch (e) {
  if (e.name == 'MyRangeError') {
    alert('My Error: ' + e.name + ' Message: ' + e.message);
  }
  else {
    alert(e.name + ' Message: ' + e.message);
  }
}

Conclusion

Including Error Handling in your scripts is not only the right thing to do, but if you really want to do it right, your visitors/users and developers would be well served by including more precise error trapping. The Java standard is to subclass generic error types in your own methods. There are no drawbacks to doing the same in JavaScript.

No comments:

Post a Comment