The previous words
Error handling is crucial for web application development. It cannot predict possible errors in advance, and recovery strategies cannot be adopted in advance, which may lead to a poor user experience. Since any javascript error can cause the web page to be unusable, as a developer, you must know when, why, and what will happen. This article will introduce the error handling mechanism in javascript in detail
error object
The error object is an object containing error information and is a native object of javascript. When an error occurs during code parsing or running, the javascript engine will automatically generate and throw an instance of the error object, and then the entire program will be interrupted where the error occurs.
console.log(t);//Uncaught ReferenceError: t is not defined
ECMA-262 specifies that an error object includes two properties: message and name. The message attribute saves the error message, while the name attribute saves the error type
The code copy is as follows:
//Generally, use the try-catch statement to catch errors
try{
t;
}catch(ex){
console.log(ex.message);//t is not defined
console.log(ex.name);//ReferenceError
}
The browser also expanded the properties of the error object and added other relevant information. Among them, the most implemented by browser manufacturers is the stack attribute, which indicates stack trace information (safari does not support it)
The code copy is as follows:
try{
t;
}catch(ex){
console.log(ex.stack);//@file:///D:/wamp/www/form.html:12:2
}
Of course, you can use the error() constructor to create an error object. If the message parameter is specified, the error object will use it as its message property; if not specified, it will use a predefined default string as the value of the property
The code copy is as follows:
new Error();
new Error(message);
//Generally, use throw statement to throw errors
throw new Error('test');//Uncaught Error: test
throw new Error();//Uncaught Error
The code copy is as follows:
function UserError(message) {
this.message = message;
this.name = "UserError";
}
UserError.prototype = new Error();
UserError.prototype.constructor = UserError;
throw new UserError("errorMessage");//Uncaught UserError: errorMessage
When the Error() constructor is called directly like a function without using the new operator, its behavior is the same as when the new operator is called
The code copy is as follows:
Error();
Error(message);
throw Error('test');//Uncaught Error: test
throw Error();//Uncaught Error
The error object has a toString() method, which returns the message attribute of the error object.
The code copy is as follows:
var test = new Error('testError');
console.log(test.toString());//'Error: testError'
error type
There are many types of errors that may occur during code execution. Each error has a corresponding error type, and when an error occurs, an error object of the corresponding type will be thrown. ECMA-262 defines the following 7 error types:
The code copy is as follows:
Error
EvalError(eval error)
RangeError(RangeError)
ReferenceError(reference error)
SyntaxError (Syntax Error)
TypeError(type error)
URIError(URI error)
Where, Error is the base type, and other error types are inherited from this type. Therefore, all error types share a set of the same properties. Error type errors are rare, and if there are, they are also thrown by the browser; the main purpose of this base type is for developers to throw custom errors
【EvalError(eval error)】
When the eval function is not executed correctly, an EvalError error will be thrown. This error type no longer appears in ES5, but will continue to be preserved to ensure compatibility with previous codes.
【RangeError(RangeError)】
An error of the RangeError type will be triggered when a value exceeds the corresponding range, mainly including exceeding the array length range and exceeding the number value range.
The code copy is as follows:
new Array(-1);//Uncaught RangeError: Invalid array length
new Array(Number.MAX_VALUE);//Uncaught RangeError: Invalid array length
(1234).toExponential(21);//Uncaught RangeError: toExponential() argument must be between 0 and 20
(1234).toExponential(-1);////Uncaught RangeError: toExponential() argument must be between 0 and 20
【ReferenceError(reference error)】
ReferenceError will be triggered when referring to an unexistent variable or lvalue type error.
a;//Uncaught ReferenceError: a is not defined
1++;//Uncaught ReferenceError: Invalid left-hand side expression in postfix operation
【SyntaxError(SyntaxError)】
When the syntax rules are not met, a SyntaxError will be thrown (syntax error)
The code copy is as follows:
//The variable name is wrong
var 1a;//Uncaught SyntaxError: Unexpected number
// Missing brackets
console.log 'hello');//Uncaught SyntaxError: Unexpected string
【TypeError(type error)】
TypeError type error will be caused when unexpected types are stored in variables, or when accessing non-existent methods. Although the causes of errors are diverse, ultimately, it is because the type of variable does not meet the requirements when performing a specific type of operation.
The code copy is as follows:
var o = new 10;//Uncaught TypeError: 10 is not a constructor
alert('name' in true);//Uncaught TypeError: Cannot use 'in' operator to search for 'name' in true
Function.prototype.toString.call('name');//Uncaught TypeError: Function.prototype.toString is not generic
【URIError(URI Error)】
URIError is an error thrown when the parameters of URI-related functions are incorrect. It mainly involves six functions: encodeURI(), decodeURI(), encodeURIComponent(), decodeURIComponent(), escape() and unescape().
decodeURI('%2');// URIError: URI malformed
error event
Any errors that are not processed through try-catch will trigger the error event of the window object
The error event can receive three parameters: error message, URL where the error is located, and line number. In most cases, only error messages are useful because the URL only gives the location of the document, and the line number refers to a line of code that can be from embedded JavaScript code or from an external file.
To specify an error event handler, you can use DOM0 level technology or use the standard format of DOM2 level events
The code copy is as follows:
//DOM0 level
window.onerror = function(message,url,line){
alert(message);
}
//DOM2 level
window.addEventListener("error",function(message,url,line){
alert(message);
});
Whether the browser displays a standard error message depends on the return value of onerror. If the return value is false, an error message is displayed in the console; if the return value is true, it is not displayed
The code copy is as follows:
//Console displays error message
window.onerror = function(message,url,line){
alert(message);
return false;
}
a;
//The console does not display error message
window.onerror = function(message,url,line){
alert(message);
return true;
}
a;
This event handler is the last line of defense to avoid browser reporting errors. Ideally, you shouldn't use it whenever possible. As long as you can use the try-catch statement appropriately, there will be no errors handed to the browser and the error event will not be triggered.
The image also supports error events. As long as the URL in the src characteristic of the image cannot return the recognized image format, an error event will be triggered. At this time, the error event follows the DOM format and returns an event object targeting the image as the target
A warning box appears when the image is loaded. When an error event occurs, the image download process has ended, which means that it cannot be downloaded again.
The code copy is as follows:
var image = new Image();
image.src = 'smilex.gif';
image.onerror = function(e){
console.log(e);
}
throw statement and throw error
The throw statement is used to throw an error. When an error is thrown, you must specify a value to the throw statement. What type is this value? There is no requirement.
[Note] The process of throwing an error is blocked, and subsequent code will not be executed
The code copy is as follows:
throw 12345;
throw 'hello world';
throw true;
throw {name: 'javascript'};
You can use the throw statement to manually throw an Error object
The code copy is as follows:
throw new Error('something bad happened');
throw new SyntaxError('I don/'t like your syntax.');
throw new TypeError('what type of variable do you take me for?');
throw new RangeError('sorry,you just don/'t have the range.');
throw new EvalError('That doesn/'t evaluate.');
throw new URIError('URI, is that you?');
throw new ReferenceError('you didn/'t cite your references properly');
Using prototype chains can also create custom error types by inheriting Error (prototype chains are introduced in Chapter 6). At this point, you need to specify the name and message attributes for the newly created error type
The browser treats custom error types inherited from Error just like other error types. Creating a custom error is useful if you want to catch the error you throw and treat it differently from the browser error.
The code copy is as follows:
function CustomError(message){
this.name = 'CustomError';
this.message = message;
}
CustomError.prototype = new Error();
throw new CustomError('my message');
When a throw statement is encountered, the code will stop executing immediately. The code will continue to execute only if a try-catch statement captures the thrown value.
A more detailed explanation is: when an exception is thrown, the javascript interpreter will immediately stop the currently executing logic and jump to the nearby exception handler. The exception handler is written in the catch clause of the try-catch statement. If the code block that throws the exception does not have an associated catch clause, the interpreter will check the higher-level closed code block to see if it has an associated exception handler. And so on until an exception handler is found. If the function that throws the exception does not handle its try-catch statement, the exception will be propagated upwards to the code that calls the function. In this way, the exception will be propagated upward along the lexical structure of the javascript method and the call stack. If no exception handler is found, javascript will handle the exception as a program error and report it to the user
Try catch statement and catch error
ECMA-262 Edition 3 introduces the try-catch statement as a standard way to handle exceptions in JavaScript, used to catch and handle errors
Among them, the try clause defines the code block where the exceptions that need to be processed are located. The catch clause follows the try clause. When an exception occurs somewhere in the try block, the code logic inside the catch is called. The catch clause is followed by the finally block, where the cleaning code is placed. Regardless of whether an exception occurs in the try block, the logic inside the finally block will always be executed. Although catch and finally are optional, the try clause requires at least one of the two to form a complete statement with it.
All try/catch/finally statement blocks need to be enclosed with curly braces. Braces here are required. Even if there is only one statement in the clause, curly braces cannot be omitted.
try{
// Generally speaking, the code here will start from beginning to end without any problems
//But sometimes an exception is thrown, either directly thrown by the throw statement or indirectly by calling a method
}catch(e){
//If and only if an exception is thrown by the try statement block, the code here will be executed
// Here you can obtain a reference to the Error object or other values thrown by the local variable e
//The code block here can handle this exception for some reason, or ignore this exception, and can also re-throw the exception through the throw statement
} finally{
// Regardless of whether the try statement throws an exception, the logic in finally will always be executed. The ways to terminate the try statement block are:
//1. Terminate normally, execute the last statement of the statement block
//2. Terminate through break, continue or return statement
//3. Throw an exception, the exception is caught by the catch clause
//4. Throw an exception, the exception is not caught, continue to be propagated upward
}
Generally, put all the code that may throw errors in the try statement block, and put the code used for error handling in the catch block
If any code in the try block error occurs, the code execution process will be immediately exited and the catch block will be executed. At this time, the catch block will receive an object with error message. The actual information contained in this object will vary from browser to browser, but the common is that there is a message attribute that stores the error message
[Note] Be sure to name the error object. If emptying it, a syntax error will be reported.
The code copy is as follows:
try{
q;
}catch(error){
alert(error.message);//q is not defined
}
//Uncaught SyntaxError: Unexpected token )
try{
q;
}catch(){
alert(error.message);
}
catch accepts a parameter indicating the value thrown by the try code block
The code copy is as follows:
function throwIt(exception) {
try {
throw exception;
} catch (e) {
console.log('Caught: '+ e);
}
}
throwIt(3);// Caught: 3
throwIt('hello');// Caught: hello
throwIt(new Error('An error happened'));// Caught: Error: An error happened
After the catch code block catches the error, the program will not be interrupted and will continue to execute according to the normal process.
The code copy is as follows:
try{
throw "Error";
} catch (e) {
console.log(111);
}
console.log(222);
// 111
// 222
In order to catch different types of errors, judgment statements can be added to the catch code block
The code copy is as follows:
try {
foo.bar();
} catch (e) {
if (e instanceof EvalError) {
console.log(e.name + ": " + e.message);
} else if (e instanceof RangeError) {
console.log(e.name + ": " + e.message);
}
// ...
}
Although the finally clause is optional in the try-catch statement, once the finally clause is used, its code will be executed no matter what. In other words, all the code in the try statement block is executed normally, and finally clauses will be executed; if the catch statement block is executed due to an error, the finally clause will still be executed. As long as the code contains finally clauses, no matter what code is contained in the try or catch statement block - or even the return statement, the execution of the finally clause will not be prevented.
The code copy is as follows:
//The error is not caught because there is no catch statement block. After executing the finally code block, the program will be interrupted where the error is thrown.
function cleansUp() {
try {
throw new Error('Error...');
console.log('This line will not be executed');
} finally {
console.log('Complete cleaning work');
}
}
cleansUp();
// Complete the cleaning work
// Error: Something went wrong...
The code copy is as follows:
function testFinnally(){
try{
return 2;
}catch(error){
return 1;
} finally{
return 0;
}
}
testFinnally();//0
[Note] The value of the count of the return statement is obtained before the finally code block is run.
The code copy is as follows:
var count = 0;
function countUp() {
try {
return count;
} finally {
count++;
}
}
countUp();// 0
console.log(count);// 1
The code copy is as follows:
function f() {
try {
console.log(0);
throw "bug";
} catch(e) {
console.log(1);
return true; // This sentence would have been delayed until the end of the finally code block before execution
console.log(2); // will not run
} finally {
console.log(3);
return false; // This sentence will cover the previous return
console.log(4); // will not run
}
console.log(5); // will not run
}
var result = f();
// 0
// 1
// 3
console.log(result);// false
【tips】Block-level scope
A common use of try-catch statements is to create block-level scopes where declared variables are only valid inside the catch
ES6 introduces the let keyword to create a block-level scope for the variables it declares. However, in the current situation of ES3 and ES5, try-catch statements are often used to achieve similar effects
From the following code, e only exists inside the catch clause, and an error will be thrown when trying to reference it from elsewhere.
The code copy is as follows:
try{
throw new Error();//Top an error
}catch(e){
console.log(e);//Error(…)
}
console.log(e);//Uncaught ReferenceError: e is not defined
Common Errors
The core of error handling is to first know what errors will happen in the code. Since javaScript is loosely typed and does not verify the parameters of the function, the error will only occur during the code. Generally speaking, three types of errors need to be paid attention to: type conversion error, data type error, and communication error
【Type conversion error】
Type conversion error occurs when using an operator, or using another language structure of data types that may automatically convert values.
The flow control statement is prone to type conversion errors. Statements like if will automatically convert any value to a boolean before determining the next operation. Especially if statements, if used improperly, they are most likely to make mistakes.
Unused named variables are automatically assigned undefined values. The undefined value can be converted to a boolean value false, so the if statement in the following function is actually only applicable to cases where the third parameter is provided. The problem is that it is not only undefined to be converted to false, nor is it only string values that can be converted to true. For example, if the third parameter is the value 0, the test of the if statement will fail, and the test of the logarithmic value 1 will pass
The code copy is as follows:
function concat(str1,str2,str3){
var result = str1 + str2;
if(str3){ //Absolutely not like this
result += str3;
}
return result;
}
Using non-boolean values in flow control statements is an extremely common source of errors. To avoid such errors, it is necessary to pass in boolean values when conditions are compared. In fact, performing some form of comparison can achieve this
The code copy is as follows:
function concat(str1,str2,str3){
var result = str1 + str2;
if(typeof str3 == 'string'){ //More suitable
result += str3;
}
return result;
}
【Data type error】
JavaScript is loosely typed and will not be compared to ensure that their data type is correct until variables and function parameters are used. In order to ensure that data type errors will not occur, only appropriate data type detection code can be written. Data type errors are most likely to occur when passing unexpected values to plot functions
The code copy is as follows:
//Unsecure functions, any non-array value will cause errors
function reverseSort(values){
if(values){
values.sort();
values.reverse();
}
}
Another common mistake is to compare parameters with null values. Comparing with null only ensures that the corresponding values are not null and undefined. To ensure that the value passed in is valid, it is not enough to detect null values only
The code copy is as follows:
//Unsecure functions, any non-array value will cause errors
function reverseSort(values){
if(values != null){
values.sort();
values.reverse();
}
}
If an object containing the sort() method (rather than an array) is passed, it will pass the detection, but an error may occur when calling the reverse() function
The code copy is as follows:
//Unsecure functions, any non-array value will cause errors
function reverseSort(values){
if(typeof values.sort == 'function'){
values.sort();
values.reverse();
}
}
In case you know exactly what type you should pass in, it is best to use instanceof to detect its data type
The code copy is as follows:
//Safe, non-array values are ignored
function reverseSort(values){
if(values instance of Array){
values.sort();
values.reverse();
}
}
【Communication Error】
With the rise of Ajax programming, it has become commonplace for web applications to dynamically load information or functionality during their life cycle. However, any communication between JavaScript and the server may cause an error
The most common problem is that data is not encoded using encodeURIComponent() before sending it to the server
The code copy is as follows:
//mistake
http://www.yourdomain.com/?redir=http://www.sometherdomain.com?a=b&c=d
//Calling encodeURIComponent() for all strings after 'redir=' can solve this problem
http://www.yourdomain.com/?redir=http:%3A%2F%2Fwww.sometherdomain.com%3Fa%3Db%26c%3Dd