• 沒有找到結果。

Function Names

在文檔中 JavaScript: The Definitive Guide (頁 183-187)

Any legal JavaScript identifier can be a function name. Try to choose function names that are descriptive but concise. Striking the right balance is an art that comes with experience. Well-chosen function names can make a big difference in the readability (and thus maintainability) of your code.

Function names are often verbs or phrases that begin with verbs. It is a common con-vention to begin function names with a lowercase letter. When a name includes multiple words, one convention is to separate words with underscores like_this(); another convention is to begin all words after the first with an uppercase letter likeThis(). Functions that are supposed to be internal or hidden (and not part of a public API) are sometimes given names that begin with an underscore.

In some styles of programming, or within well-defined programming frameworks, it can be useful to give frequently used functions very short names. The client-side Java-Script framework jQuery (covered in Chapter 19), for example, makes heavy use in its public API of a function named $() (yes, just the dollar sign). (Recall from §2.4 that dollar signs and underscores are the two characters besides letters and numbers that are legal in JavaScript identifiers.)

As described in §5.3.2, function declaration statements are “hoisted” to the top of the enclosing script or the enclosing function, so that functions declared in this way may be invoked from code that appears before they are defined. This is not true for functions defined as expressions, however: in order to invoke a function, you must be able to refer to it, and you can’t refer to a function defined as an expression until it is assigned to a variable. Variable declarations are hoisted (see §3.10.1, but assignments to those variables are not hoisted, so functions defined with expressions cannot be invoked before they are defined.

8.1 Defining Functions | 165

Core JavaScript

Notice that most, but not all, of the functions in Example 8-1 contain a return statement (§5.6.4). The return statement causes the function to stop executing and to return the value of its expression (if any) to the caller. If the return statement does not have an associated expression, it returns the undefined value. If a function does not contain a return statement, it simply executes each statement in the function body and returns the undefined value to the caller.

Most of the functions in Example 8-1 are designed to compute a value, and they use return to return that value to their caller. The printprops() function is different: its job is to output the names and values of an object’s properties. No return value is necessary, and the function does not include a return statement. The value of an invocation of the printprops() function is always undefined. (Functions with no return value are sometimes called procedures.)

8.1.1 Nested Functions

In JavaScript, functions may be nested within other functions. For example:

function hypotenuse(a, b) {

function square(x) { return x*x; } return Math.sqrt(square(a) + square(b));

}

The interesting thing about nested functions is their variable scoping rules: they can access the parameters and variables of the function (or functions) they are nested with-in. In the code above, for example, the inner function square() can read and write the parameters a and b defined by the outer function hypotenuse(). These scope rules for nested functions are very important, and we’ll consider them again in §8.6.

As noted in §5.3.2, function declaration statements are not true statements, and the ECMAScript specification only allows them as top-level statements. They can appear in global code, or within other functions, but they cannot appear inside of loops, con-ditionals, or try/catch/finally or with statements.1 Note that this restriction applies only to functions declared as statements. Function definition expressions may appear anywhere in your JavaScript code.

8.2 Invoking Functions

The JavaScript code that makes up the body of a function is not executed when the function is defined but when it is invoked. JavaScript functions can be invoked in four ways:

• as functions,

• as methods,

1. Some JavaScript implementations relax this rule. Firefox, for example, allows “conditional function declarations” that appear within if statements.

• as constructors, and

• indirectly through their call() and apply() methods.

8.2.1 Function Invocation

Functions are invoked as functions or as methods with an invocation expression (§4.5). An invocation expression consists of a function expression that evaluates to a function object followed by an open parenthesis, a comma-separated list of zero or more argument expressions, and a close parenthesis. If the function expression is a property-access expression—if the function is the property of an object or an element of an array—then it is a method invocation expression. That case will be explained below. The following code includes a number of regular function invocation expressions:

printprops({x:1});

var total = distance(0,0,2,1) + distance(2,1,3,5);

var probability = factorial(5)/factorial(13);

In an invocation, each argument expression (the ones between the parentheses) is eval-uated, and the resulting values become the arguments to the function. These values are assigned to the parameters named in the function definition. In the body of the function, a reference to a parameter evaluates to the corresponding argument value.

For regular function invocation, the return value of the function becomes the value of the invocation expression. If the function returns because the interpreter reaches the end, the return value is undefined. If the function returns because the interpreter exe-cutes a return, the return value is the value of the expression that follows the return or undefined if the return statement has no value.

For function invocation in ECMAScript 3 and nonstrict ECMAScript 5, the invocation context (the this value) is the global object. In strict mode, however, the invocation context is undefined.

Functions written to be invoked as functions do not typically use the this keyword at all. It can be used, however, to determine whether strict mode is in effect:

// Define and invoke a function to determine if we're in strict mode.

var strict = (function() { return !this; }());

8.2.2 Method Invocation

A method is nothing more than a JavaScript function that is stored in a property of an object. If you have a function f and an object o, you can define a method named m of o with the following line:

o.m = f;

Having defined the method m() of the object o, invoke it like this:

o.m();

8.2 Invoking Functions | 167

Core JavaScript

Download from Wow! eBook <www.wowebook.com>

Or, if m() expects two arguments, you might invoke it like this:

o.m(x, y);

The code above is an invocation expression: it includes a function expression o.m and two argument expressions, x and y. The function expression is itself a property access expression (§4.4), and this means that the function is invoked as a method rather than as a regular function.

The arguments and return value of a method invocation are handled exactly as descri-bed above for regular function invocation. Method invocations differ from function invocations in one important way, however: the invocation context. Property access expressions consist of two parts: an object (in this case o) and a property name (m). In a method invocation expression like this, the object o becomes the invocation context, and the function body can refer to that object by using the keyword this. Here is a concrete example:

var calculator = { // An object literal operand1: 1,

operand2: 1, add: function() {

// Note the use of the this keyword to refer to this object.

this.result = this.operand1 + this.operand2;

} };

calculator.add(); // A method invocation to compute 1+1.

calculator.result // => 2

Most method invocations use the dot notation for property access, but property access expressions that use square brackets also cause method invocation. The following are both method invocations, for example:

o["m"](x,y); // Another way to write o.m(x,y).

a[0](z) // Also a method invocation (assuming a[0] is a function).

Method invocations may also involve more complex property access expressions:

customer.surname.toUpperCase(); // Invoke method on customer.surname f().m(); // Invoke method m() on return value of f()

Methods and the this keyword are central to the object-oriented programming para-digm. Any function that is used as a method is effectively passed an implicit argument—

the object through which it is invoked. Typically, a method performs some sort of operation on that object, and the method-invocation syntax is an elegant way to express the fact that a function is operating on an object. Compare the following two lines:

rect.setSize(width, height);

setRectSize(rect, width, height);

The hypothetical functions invoked in these two lines of code may perform exactly the same operation on the (hypothetical) object rect, but the method-invocation syntax in the first line more clearly indicates the idea that it is the object rect that is the primary focus of the operation.

在文檔中 JavaScript: The Definitive Guide (頁 183-187)