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

JavaScript Bible, Gold Edition part 125 doc

10 37 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 197,51 KB

Nội dung

1088 Part IV ✦ JavaScript Core Language Reference The conditional operator is a shortcut way of expressing an if. . .else conditional construction covered in Chapter 39. This operator is typically used in concert with an assignment operator to assign one of two values to a variable based on the result of a condition expression. The formal syntax for the conditional operator is: condition ? expressionIfTrue : expressionIfFalse If used with an assignment operator, the syntax is: var = condition ? expressionIfTrue : expressionIfFalse No matter how you use the operator, the important point to remember is that an expression that contains this operator evaluates to one of the two expressions following the question mark symbol. In truth, either expression could invoke any JavaScript, including calling other functions or even nesting further conditional operators within one of the expressions to achieve the equivalent of nested if. . .else constructions. To assure proper resolution of nested conditionals, surround inner expressions with parentheses to make sure that they evaluate before the outer expression evaluates. As an example, the following statement assigns one of three strings to a variable depending on the date within a month: var monthPart = (dateNum <= 10) ? “early” : ((dateNum <= 20) ? “middle” : “late”) When the statement is evaluated, the inner conditional expression at the right of the first colon is evaluated, returning either middle or late; then the outer conditional expression is evaluated, returning either early or the result of the inner conditional expression. typeof NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓✓ ✓ ✓ ✓✓✓ Unlike most other operators, which are predominantly concerned with arithmetic and logic, the unary typeof operator defines the kind of value to which a variable or expression evaluates. Typically, this operator is used to identify whether a variable value is one of the following types: number, string, boolean, object, function, or undefined. Having this investigative capability in JavaScript is helpful because variables cannot only contain any one of those data types but can change their data type on the fly. Your scripts may need to handle a value differently based on the value’s type. The most common use of the typeof property is as part of a condition. For example: if (typeof myVal == “number”) { myVal = parseInt(myVal) } The evaluated value of the typeof operation is, itself, a string. typeof 1089 Chapter 40 ✦ JavaScript Operators void NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓✓ ✓ ✓✓✓ In all scriptable browsers you can use the javascript: pseudo-protocol to supply the parameter for HREF and SRC attributes in HTML tags, such as links. In the process, you have to be careful that the function or statement being invoked by the URL does not return or evaluate to any values. If a value comes back from such an expression, then that value or sometimes the directory of the client’s hard disk often replaces the page content. To avoid this possibility use the void operator in front of the function or expression being invoked by the javascript: URL. The best way to use this construction is to place the operator before the expression or function and separate them by a space, as in javascript: void doSomething() On occasion, you may have to wrap the expression inside parentheses after the void operator. Using parantheses is necessary only when the expression contains operators of a lower precedence than the void operator (see the following section, “Operator Precedence”). But don’t automatically wrap all expressions in parenthe- ses, because some browsers can experience problems with these. Even so, it is common practice to assign the following URL to the HREF attribute of an A link whose onClick event handler does all of the work: HREF=”javascript: void (0)” The void operator makes sure the function or expression returns no value that the HTML attribute can use. Such a link’s onClick event handler should also inhibit the natural behavior of a clicked link (for example, by evaluating to return false). Operator Precedence When you start working with complex expressions that hold a number of opera- tors (for example, Listing 40-2), knowing the order in which JavaScript evaluates those expressions is vital. JavaScript assigns different priorities or weights to types of operators in an effort to achieve uniformity in the way it evaluates complex expressions. In the following expression 10 + 4 * 5 // result = 30 JavaScript uses its precedence scheme to perform the multiplication before the addition — regardless of where the operators appear in the statement. In other words, JavaScript first multiplies 4 by 5, and then adds that result to 10 to get a result of 30. That may not be the way you want this expression to evaluate. Perhaps your intention was to add the 10 and 4 first and then to multiply that sum by 5. To make that happen, you have to override JavaScript’s natural operator precedence. To do that, you must use parentheses to enclose an operator with lower precedence. void 1090 Part IV ✦ JavaScript Core Language Reference The following statement shows how you adjust the previous expression to make it behave differently: (10 + 4) * 5 // result = 70 That one set of parentheses has a great impact on the outcome. Parentheses have the highest precedence in JavaScript, and if you nest parentheses in an expression, the innermost set evaluates first. For help in constructing complex expressions, refer to Table 40-10 for JavaScript’s operator precedence. My general practice: When in doubt about complex precedence issues, I build the expression with lots of parentheses according to the way I want the internal expressions to evaluate. Table 40-10: JavaScript Operator Precedence Precedence Level Operator Notes 1 () From innermost to outermost [] Array index value function() Any remote function call 2 ! Boolean Not ~ Bitwise Not - Negation ++ Increment Decrement new typeof void delete Delete array or object entry 3 * Multiplication / Division % Modulo 4 + Addition - Subtraction 5 << Bitwise shifts > >> 6 < Comparison operators <= 1091 Chapter 40 ✦ JavaScript Operators Precedence Level Operator Notes > >= 7 == Equality != 8 & Bitwise And 9 ^ Bitwise XOR 10 | Bitwise Or 11 && Boolean And 12 || Boolean Or 13 ? Conditional expression 14 = Assignment operators += -= *= /= %= <<= >= >>= &= ^= |= 15 , Comma (parameter delimiter) This precedence scheme is devised to help you avoid being faced with two operators from the same precedence level that often appear in the same expression. When it happens (such as with addition and subtraction), JavaScript begins evalu- ating the expression from left to right. One related fact involves a string of Boolean expressions strung together for a condition statement (Listing 40-2). JavaScript follows what is called short-circuit evaluation. As the nested expressions are evaluated left to right, the fate of the entire condition can sometimes be determined before all expressions are evaluated. Any time JavaScript encounters an And operator, if the left operand evaluates to false, the entire expression evaluates to false without JavaScript’s even bothering to evaluate the right operand. For an Or operator, if the left operand is true, JavaScript short-circuits that expression to true. This feature can trip you up if you don’t perform enough testing on your scripts: If a syntax error or other error exists 1092 Part IV ✦ JavaScript Core Language Reference in a right operand, and you fail to test the expression in a way that forces that right operand to evaluate, you may not know that a bug exists in your code. Users of your page, of course, will find the bug quickly. Do your testing to head bugs off at the pass. Notice, too, that all math and string concatenation is performed prior to any comparison operators. This enables all expressions that act as operands for comparisons to evaluate fully before they are compared. The key to working with complex expressions is to isolate individual expressions and to try them out by themselves, if you can. See additional debugging tips in Chapter 45. ✦✦✦ Note Functions and Custom Objects B y now, you’ve seen dozens of JavaScript functions in action and probably have a pretty good feel for the way they work. This chapter provides the function object specification and delves into the fun prospect of creating objects in your JavaScript code. (That includes objects that have properties and methods, just like the big boys.) Function Object Properties Methods arguments apply() arity call() caller toString() constructor valueOf() length prototype Syntax Creating a function object: function functionName([arg1, [,argN]]) { statement(s) } var funcName = new Function([“argName1”, [,”argNameN”], “statement1; [;statementN]”]) object.eventHandlerName = function([arg1, [,argN]]) {statement(s)} Accessing function object properties and methods: functionObject.property | method([parameters]) 41 41 CHAPTER ✦✦✦✦ In This Chapter Creating function blocks Passing parameters to functions Creating your own objects ✦✦✦✦ 1094 Part IV ✦ JavaScript Core Language Reference NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility (✓) ✓✓✓(✓) ✓✓✓✓ About this object JavaScript accommodates what other languages might call procedures, subrou- tines, and functions all in one type of structure: the custom function. A function may return a value (if programmed to do so with the return keyword), but it does not have to return any value. Except for JavaScript code that executes as the document loads, all deferred processing takes place in functions. While you can create functions that are hundreds of lines long, I recommend you break up longer processes into shorter functions. Among the reasons for doing so: smaller chunks are easier to write and debug; building blocks make it easier to visu- alize the entire script; you can make functions generalizable and reusable for other scripts; and other parts of the script or other open frames can use the functions. Learning how to write good, reusable functions takes time and experience. But the earlier you understand the importance of this concept, the more you will be on the lookout for good examples in other people’s scripts on the Web. Creating functions The standard way of defining a function in your script means following a simple pattern and then filling in the details. The formal syntax definition for a function is: function functionName( [arg1] [, argN]) { statement(s) } The task of assigning a function name helps you determine the precise scope of activity of the function. If you find that you can’t reduce the planned task for the function to a simple one- to three-word name (which is then condensed into one contiguous sequence of characters for the functionName), perhaps you’re asking the function to do too much. A better idea may be to break the job into two or more functions. As you start to design a function, be on the lookout for functions that you can call from the one you’re writing. If you find yourself copying and pasting lines of code from one part of a function to another because you’re performing the same operation in different spots within the function, it may be time to break that segment out into its own function. Starting with Navigator 3 (and Internet Explorer 3 with JScript.dll version2), you can also create what is called an anonymous function using the new Function() constructor. In reality, you assign a name to this “anonymous” function as follows: var funcName = new Function([“argName1”, [,”argNameN”], “statement1; [;statementN]”]) This other way of building a function is particularly helpful when your scripts need to create a function after a document loads. All the components of a function are present in this definition. Each function parameter name is supplied as a string value, separated from each other by commas. The final parameter string consists of functionObject 1095 Chapter 41 ✦ Functions and Custom Objects the statements that execute whenever the function is called. Separate each JavaScript statement with a semicolon, and enclose the entire sequence of state- ments inside quotes, as in the following: var willItFit = new Function(“width”,”height”, “var sx = screen.availWidth; var sy = screen.availHeight; return (sx >= width && sy >= height)”) The willItFit() function takes two parameters; the body of the function defines two local variables ( sx and sy) and then returns a Boolean value of true if the incoming parameters are smaller than the local variables. In traditional form, this function is defined as follows: function willItFit(width, height) { var sx = screen.availWidth var sy = screen.availHeight return (sx >= width && sy >= height) } Once this function exists in the browser’s memory, you can invoke it like any other function: if (willItFit(400,500)) { statements to load image } One last function creation format is available in NN4+. This advanced technique, called a lambda expression, provides a shortcut for creating a reference to an anonymous function (truly anonymous because the function has no name that you can reference later). The common application of this technique is to assign function references to event handlers when the NN event object also must be passed. The following is an example of how to assign an anonymous function to an onChange event handler for a form control: document.forms[0].age.onchange = function(event) {isNumber(document.forms[0].age)} Nesting functions NN4+ and IE4+ also provide for nesting functions inside one another. In all prior scripting, each function definition is defined at the global level whereby every func- tion is exposed and available to all other scripting. With nested functions, you can encapsulate the exposure of a function inside another and make that nested func- tion private to the enclosing function. Of course I don’t recommend reusing names in this fashion, but you can create nested functions with the same name inside mul- tiple global level functions, as the following skeletal structure shows: function outerA() { statements function innerA() { statements } statements } functionObject 1096 Part IV ✦ JavaScript Core Language Reference function outerB() { statements function innerA() { statements } function innerB() { statements } statements } A good time to apply a nested function is when a sequence of statements need to be invoked in multiple places within a large function but those statements have meaning only within the context of the larger function. In other words, rather than break out the repeated sequence as a separate global function, you keep it all within the scope of the larger function. You can access a nested function only from statements in its containing function (and in any order). Moreover, all variables defined in the outer function (including parameter variables) are accessible to the inner function; but variables defined in an inner function are not accessible to the outer function. See the section, “Variable Scope: Globals and Locals” later in this chapter for details on how variables are visible to various components of a script. Function parameters The function definition requires a set of parentheses after the functionName. If the function does not rely on any information arriving with it when invoked, the parentheses can be empty. But when some kind of data is arriving with a call to the function, you need to assign names to each parameter. Virtually any kind of value can be a parameter: strings, numbers, Booleans, and even complete object refer- ences such as a form or form element. Choose names for these variables that help you remember the content of those values; also, avoid reusing existing object names as variable names because it’s easy to get confused when objects and variables with the same name appear in the same statements. You must avoid using JavaScript keywords (including the reserved words listed in Appendix B) and any global variable name defined elsewhere in your script. (See more about global variables in the following sections.) JavaScript is forgiving about matching the number of parameters in the function definition with the number of parameters passed along from the calling statement. If you define a function with three parameters and the calling statement specifies only two, the third parameter variable value in that function is assigned a null value. For example: function oneFunction(a, b, c) { statements } oneFunction(“George”,”Gracie”) In the preceding example, the values of a and b inside the function are “George” and “Gracie”, respectively; the value of c is null. functionObject 1097 Chapter 41 ✦ Functions and Custom Objects At the opposite end of the spectrum, JavaScript also doesn’t balk if you send more parameters from the calling statement than the number of parameter variables specified in the function definition. In fact, the language includes a mechanism — the arguments property — that you can add to your function to gather any extraneous parameters that should read your function. Properties arguments Value: Array of arguments Read-Only NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓✓ ✓ ✓✓✓ When a function receives parameter values from the statement that invokes the function, those parameter values are silently assigned to the arguments property of the function object. This property is an array of the values, with each parameter value assigned to a zero-based index entry in the array — whether or not parame- ters are defined for it. You can find out how many parameters are sent by extracting functionName.arguments.length. For example, if four parameters are passed, functionName.arguments.length returns 4. Then, you can use array notation ( functionName.arguments[i]) to extract the values of any parameter(s) you want. Theoretically, you never have to define parameter variables for your functions by extracting the desired arguments array entry instead. Well-chosen parameter variable names, however, are much more readable, so I recommend them over the arguments property in most cases. But you may run into situations in which a sin- gle function definition needs to handle multiple calls to the function when each call may have a different number of parameters. The function knows how to handle any arguments over and above the ones given names as parameter variables. See Listings 41-1 and 41-2 for a demonstration of both the arguments and caller properties. arity Value: Integer Read-Only NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓ See the discussion of the length property later in this chapter. functionObject.arity . happen, you have to override JavaScript s natural operator precedence. To do that, you must use parentheses to enclose an operator with lower precedence. void 1090 Part IV ✦ JavaScript Core Language. true, JavaScript short-circuits that expression to true. This feature can trip you up if you don’t perform enough testing on your scripts: If a syntax error or other error exists 1092 Part IV ✦ JavaScript. your own objects ✦✦✦✦ 1094 Part IV ✦ JavaScript Core Language Reference NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility (✓) ✓✓✓(✓) ✓✓✓✓ About this object JavaScript accommodates what

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