1. Trang chủ
  2. » Công Nghệ Thông Tin

JavaScript Bible, Gold Edition part 122 pdf

10 153 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 93,44 KB

Nội dung

1058 Part IV ✦ JavaScript Core Language Reference The single catch block in Listing 39-7 executes only if one of the statements in the try block throws an exception. The exceptions may be not only one of the four specific ones named in the catch block but also syntax or other errors that could occur inside the try block. That’s why you have a last-ditch case to handle truly unexpected errors. Your job as scripter is to not only anticipate errors but also to provide clean ways for the exceptions to be handled, whether they be through judi- ciously worded alert dialog boxes or perhaps even some self-repair. For example, in the case of the invalid character error for createElement(), your script may attempt to salvage the data passed to the attachToEnd() function and reinvoke the method passing theNode value as-is and the repaired value originally passed to newTag. If your repairs were successful, the try block would execute without error and carry on with the user’s being completely unaware that a nasty problem had been averted. A finally block contains code that always executes after a try block, whether or not the try block succeeds without throwing an error. Unlike the catch block, a finally block does not receive an error object as a parameter, so it operates very much in the dark about what transpires inside the try block. If you include both catch and finally blocks after a try block, the execution path depends on whether an exception is thrown. If no exception is thrown, the finally block exe- cutes after the last statement of the try block runs. But if the try block throws an exception, program execution runs first to the catch block. After all processing within the catch block finishes, the finally block executes. In development envi- ronments that give programmers complete control over resources, such as memory allocation, a finally block may be used to delete some temporary items generated in the try block, whether or not an exception occurs in the try block. Currently, JavaScript has less need for that kind of maintenance, but you should be aware of the program execution possibilities of the finally block in the try-catch-finally context. Real-life exceptions The example shown in Listing 39-6 is a bit idealized. The listing assumes that the browser dutifully reports every W3C DOM exception precisely as defined in the for- mal specification. Unfortunately, that’s not how it is (yet) in browsers through IE5.5 and NN6. Both browsers implement additional error naming conventions and layers between actual DOM exceptions and what gets reported with the error object at the time of the exception. If you think these discrepancies make cross-browser exception handling difficult, you’re right. Even simple errors are reported differently among the two major browser brands and the W3C DOM specification. Until the browsers exhibit a greater unanimity in exception reporting, the smoothest development road will be for those scripters who have the luxury of writing for one of the browser platforms, such as IE5 for Windows or NN6. That said, however, one aspect of exception handling can still be used in both IE5+ and NN6. You can take advantage of try-catch constructions to throw your own exceptions — a practice that is quite common in advanced programming environments. try-catch-finally 1059 Chapter 39 ✦ Control Structures and Exception Handling Throwing Exceptions The last exception handling keyword not covered yet — throw — makes it possi- ble to utilize exception handling facilities for your own management of processes, such as data entry validation. At any point inside a try block, you can manually throw an exception that gets picked up by the associated catch block. The details of the specific exception are up to you. Syntax for the throw statement is as follows: throw value The value you throw can be of any type, but good practice suggests that the value be an error object (described more fully later in this chapter). Whatever value you throw is assigned to the parameter of the catch block. Look at the fol- lowing two examples. In the first, the value is a string message; in the second, the value is an error object. Listing 39-8 presents one input text box for a number between 1 and 5. Clicking a button looks up a corresponding letter in an array and displays the letter in a sec- ond text box. The lookup script has two simple data validation routines to make sure the entry is a number and is in the desired range. Error checking here is done manually by script. If either of the error conditions occurs, throw statements force execution to jump to the catch block. The catch block assigns the incoming string parameter to the variable e. The design here assumes that the message being passed is text for an alert dialog box. Not only does a single catch block take care of both error conditions (and conceivably any others to be added later), but the catch block runs within the same variable scope as the function, so that it can use the reference to the input text box to focus and select the input text if there is an error. Listing 39-8: Throwing String Exceptions <HTML> <HEAD> <TITLE>Throwing a String Exception</TITLE> <SCRIPT LANGUAGE=”JavaScript”> var letters = new Array(“A”,”B”,”C”,”D”,”E”) function getLetter(fld) { try { var inp = parseInt(fld.value, 10) if (isNaN(inp)) { throw “Entry was not a number.” } if (inp < 1 || inp > 5) { throw “Enter only 1 through 5.” } fld.form.output.value = letters[inp] } catch (e) { alert(e) fld.form.output.value = “” Continued throw 1060 Part IV ✦ JavaScript Core Language Reference Listing 39-8 (continued) fld.focus() fld.select() } } </SCRIPT> </HEAD> <BODY> <H1>Throwing a String Exception</H1> <HR> <FORM> Enter a number from 1 to 5: <INPUT TYPE=”text” NAME=”input” SIZE=5> <INPUT TYPE=”button” VALUE=”Get Letter” onClick=getLetter(this.form.input)> Matching Letter is:<INPUT TYPE=”text” NAME=”output” SIZE=5> </FORM> </BODY> </HTML> The flaw with Listing 39-8 is that if some other kind of exception were thrown inside the try block, the value passed to the catch block would be an error object, not a string. The alert dialog box displayed to the user would be meaningless. Therefore, it is better to be uniform in your throw-catch constructions and pass an error object. Listing 39-9 is an updated version of Listing 39-8, demonstrating how to create an error object that gets sent to the catch block via throw statements. The one glitch in generating an error object comes in IE5 and IE5.5. The ECMA-262 standard allows a script statement to set the message property of an error object to directly by passing a string as the parameter to the new Error() constructor. This is how NN6 works. But the error object in IE5 does not have the message property at all, and in IE5.5, the parameter is not assigned to the message property. Therefore, Listing 39-9 contains a separate utility function ( getErrorObj()) that fills the gap when an error object does not have the message property to begin with or doesn’t have the property set automatically. If a future version of IE adopts the ECMA standard way, then the extra branch is avoided, just as it is for NN6. Listing 39-9: Throwing an Error Object Exception <HTML> <HEAD> <TITLE>Throwing an Error Object Exception</TITLE> <SCRIPT LANGUAGE=”JavaScript”> var letters = new Array(“A”,”B”,”C”,”D”,”E”) function getErrorObj(msg) { var err = new Error(msg) // take care of IE5/5.5 if (!err.message) { throw 1061 Chapter 39 ✦ Control Structures and Exception Handling err.message = msg } return err } function getLetter(fld) { try { var inp = parseInt(fld.value, 10) if (isNaN(inp)) { throw getErrorObj(“Entry was not a number.”) } if (inp < 1 || inp > 5) { throw getErrorObj(“Enter only 1 through 5.”) } fld.form.output.value = letters[inp] } catch (e) { alert(e.message) fld.form.output.value = “” fld.focus() fld.select() } } </SCRIPT> </HEAD> <BODY> <H1>Throwing an Error Object Exception</H1> <HR> <FORM> Enter a number from 1 to 5: <INPUT TYPE=”text” NAME=”input” SIZE=5> <INPUT TYPE=”button” VALUE=”Get Letter” onClick=getLetter(this.form.input)> Matching Letter is:<INPUT TYPE=”text” NAME=”output” SIZE=5> </FORM> </BODY> </HTML> The only difference to the catch block is that it now reads the message property of the incoming error object. This means that if some other exception is thrown inside the try block, the browser-generated message will be displayed in the alert dialog box. In truth, however, the job really isn’t complete. In all likelihood, if a browser- generated exception is thrown, the message in the alert dialog box won’t mean much to the user. The error message will probably be some kind of syntax or type error — the kind of meaningless error message you often get from your favorite operating system. A better design is to branch the catch block so that “intentional” exceptions thrown by your code are handled through the alert dialog box messages you’ve put there, but other types are treated differently. To accomplish this, you can take over one of the other properties of the error object — name — so that your catch block treats your custom messages separately. throw 1062 Part IV ✦ JavaScript Core Language Reference In Listing 39-10, the getErrorObj() function adds a custom value to the name property of the newly created error object. The name you assign can be any name, but you want to avoid exception names used by JavaScript or the DOM. Even if you don’t know what all of those are, you can probably conjure up a suitably unique name for your error. Down in the catch block, a switch construction branches to treat the two classes of errors differently. Notice that because IE5’s error object does not have a name property, the switch expression (e.name) evaluates to undefined, which forces the default case to execute whenever a native exception is thrown (and you have to be careful about which error object properties you use in the default case statements). In this simplified example, about the only possi- ble problem other than the ones being trapped for explicitly in the try block would be some corruption to the page during downloading. Therefore, for this example, the branch for all other errors simply asks that the user reload the page and try again. The point is, however, that you can have as many classifications of custom and system errors as you want and handle them in a single catch block accordingly. Listing 39-10: A Custom Object Exception <HTML> <HEAD> <TITLE>Throwing a Custom Error Object Exception</TITLE> <SCRIPT LANGUAGE=”JavaScript”> var letters = new Array(“A”,”B”,”C”,”D”,”E”) function getErrorObj(msg) { var err = new Error(msg) // take care of IE5/5.5 if (!err.message) { err.message = msg } err.name = “MY_ERROR” return err } function getLetter(fld) { try { var inp = parseInt(fld.value, 10) if (isNaN(inp)) { throw getErrorObj(“Entry was not a number.”) } if (inp < 1 || inp > 5) { throw getErrorObj(“Enter only 1 through 5.”) } fld.form.output.value = letters[inp] } catch (e) { switch (e.name) { case “MY_ERROR” : alert(e.message) fld.form.output.value = “” fld.focus() fld.select() throw 1063 Chapter 39 ✦ Control Structures and Exception Handling break default : alert(“Reload the page and try again.”) } } } </SCRIPT> </HEAD> <BODY> <H1>Throwing a Custom Error Object Exception</H1> <HR> <FORM> Enter a number from 1 to 5: <INPUT TYPE=”text” NAME=”input” SIZE=5> <INPUT TYPE=”button” VALUE=”Get Letter” onClick=getLetter(this.form.input)> Matching Letter is:<INPUT TYPE=”text” NAME=”output” SIZE=5> </FORM> </BODY> </HTML> If you want to see how the alternative branch of Listing 39-10 looks, copy the list- ing file from the CD-ROM to your hard disk and modify the last line of the try block so that one of the letters is dropped from the name of the array: fld.form.output.value = letter[inp] This may simulate the faulty loading of the page. If you enter one of the allowable values, the reload alert appears, rather than the actual message of the error object: letter is undefined. Your users will thank you. All that’s left now on this subject are the details on the error object. Error Object Properties Methods Error.prototype errorObject.toString() errorObject.constructor errorObject.description errorObject.filename errorObject.lineNumber errorObject.message errorObject.name errorObject.number errorObject 1064 Part IV ✦ JavaScript Core Language Reference Syntax Creating an error object: var myError = new Error(“message”) var myError = Error(“message”) Accessing static Error object property: Error.property Accessing error object properties and methods: errorObject.property | method([parameters]) NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓✓ About this object An error object instance is created whenever an exception is thrown or when you invoke either of the constructor formats for creating an error object. Properties of the error object instance contain information about the nature of the error so that catch blocks can inspect the error and process error handling accordingly. IE5 implemented an error object in advance of the ECMA-262 formal error object, and the IE5 version ends up having its own set of properties that are not part of the ECMA standard. Those proprietary properties are still part of IE5.5, which includes the ECMA properties as well. NN6, on the other hand, starts with the ECMA proper- ties and adds two proprietary properties of its own. The browser uses these addi- tional properties in its own script error reporting. The unfortunate bottom line for cross-browser developers is that no properties in common among all browsers sup- port the error object. However, two common denominators ( name and message) are between IE5.5 and NN6. As described earlier in this chapter, you are encouraged to create an error object whenever you use the throw statement for your own error control. See the discus- sion surrounding Listing 39-9 about handling missing properties in IE. Properties constructor See string.constructor (Chapter 34). description Value: String Read/Write NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓ errorObject.description 1065 Chapter 39 ✦ Control Structures and Exception Handling The description property contains a descriptive string that provides some level of detail about the error. For errors thrown by the browser, the description is the same text that appears in the script error dialog box in IE. Although this prop- erty continues to be supported, the message property in IE5.5 and NN6 is preferred. Related Items: message property. fileName lineNumber Value: String Read/Write NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓ The NN6 browser uses the fileName and lineNumber properties of an error object for its own internal script error processing — these values appear as part of the error messages that are listed in the JavaScript Console. The fileName is the URL of the document causing the error; the lineNumber is the source code line number of the statement that threw the exception. These properties are exposed to JavaScript, as well, so that your error processing may use this information if it is meaningful to your application. Both of these properties (along with the message property) have been in the Navigator vernacular since NN3. See the discussion of the window.error property in Chapter 16 for further ideas on how to use this information for bug reporting from users. Related Items: window.error property. message Value: String Read/Write NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓ The message property contains a descriptive string that provides some level of detail about the error. For errors thrown by the browser, the message is the same text that appears in the script error dialog box in IE and the JavaScript Console in NN6. By and large, these messages are more meaningful to scripters than to users. Unfortunately, there are no standards for the wording of a message for a given error. Therefore, it is hazardous at best to use the message content in a catch block as a means of branching to handle particular kinds of errors. You may get by with this approach if you are developing for a single browser platform, but you have no assurances that the text of a message for a particular exception may not change in future browser versions. errorObject.message 1066 Part IV ✦ JavaScript Core Language Reference Custom messages for errors that your code explicitly throws can be in user- friendly language if you intend to display such messages to users. See Listings 39-8 through 39-10 for examples of this usage. Related Items: description property. name Value: String Read/Write NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓ The name property generally contains a word that identifies the type of error that has been thrown. The most general kind of error (and the one that is created via the new Error() constructor) has a name Error. But JavaScript errors can be of several varieties: EvalError, RangeError, ReferenceError, SyntaxError, TypeError, and URIError. Some of these error types are not necessarily intended for exposure to scripters (they’re used primarily in the inner workings of the JavaScript engine), but some browsers do expose them. Unfortunately, there are some discrepancies as to the specific name supplied to this property for script errors. When JavaScript is being used in a browser environment that employs the W3C DOM, some DOM exception types are returned via the name property. But browsers frequently insert their own error types for this property, and, as is common in this department, little uniformity exists among browser brands. For custom exceptions that your code explicitly throws, you can assign names as you want. As shown in Listings 39-9 and 39-10, this information can assist a catch block in handling multiple categories of errors. Related Items: message property. number Value: Number Read/Write NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓ IE5+ assigns unique numbers to each error description or message. The number property, however, is problematical. While Microsoft documents a sequence of syn- tax and runtime errors and their numbers, in practice, IE browsers do not report the numbers shown in Microsoft’s own documentation. This is unfortunate, because the number can be a language-independent way of branching catch block code based on the error number, rather than the description or message. And, errorObject.number 1067 Chapter 39 ✦ Control Structures and Exception Handling because the number property was born at the same time as the description prop- erty (now superseded by the message property), it is unknown how reliable the number values (if you can figure them out) will be going forward. Related Items: description property. Methods toString() Returns: String (see text). NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓✓ The toString() method for an error object should return a string description of the error. In IE5 and 5.5, however, the method returns a reference to the very same error object. In NN6, the method returns the message property string, preceded by the string Error: (with a space after the colon). Most typically, if you want to retrieve a human-readable expression of an error object, read its message (or, in IE5, description) property. Related Items: message property. ✦✦✦ errorObject.toString() . 1058 Part IV ✦ JavaScript Core Language Reference The single catch block in Listing 39-7 executes only if. 5.” } fld.form.output.value = letters[inp] } catch (e) { alert(e) fld.form.output.value = “” Continued throw 1060 Part IV ✦ JavaScript Core Language Reference Listing 39-8 (continued) fld.focus() fld.select() } } </SCRIPT> </HEAD> <BODY> <H1>Throwing. object — name — so that your catch block treats your custom messages separately. throw 1062 Part IV ✦ JavaScript Core Language Reference In Listing 39-10, the getErrorObj() function adds a custom

Ngày đăng: 06/07/2014, 06:20