Section 5.1. Defining a Function: Let Me Count the Ways


5.1. Defining a Function: Let Me Count the Ways

There are three primary approaches to creating functions in JavaScript: declarative/static, dynamic/anonymous, and literal. It's important to understand the impact of each type of declaration before using it.

Many programming tasks can be accomplished with the simple declarative/static approach. You may not want to use anonymous or literal functions while getting started, but it's useful to know what they are if you have to read someone else's code. (And eventually, of course, you'll probably want to use them!)


5.1.1. Declarative Functions

The most common type of function uses the declarative/static format. This approach begins with the function keyword, followed by function name, parentheses containing zero or more arguments, and then the function body:

function functionname (param1, param2, ..., paramn) {    function statements }

Unless I'm creating a new library with new objects, or defining functions on the fly based on events, this tends to be the syntax I use the most.

The declarative/static function is parsed once, when the page is loaded, and the parsed result is used each time the function is called. It's easy to spot in the code, simple to read and understand, and has no negative consequences (usually), such as memory leaks. It's also more familiar to developers who have worked with other programming languages.

This type of function has been demonstrated extensively in the previous chapters, so I won't provide a full example of its use here. The following snippet of code creates a function that uses this function format, which is called immediately after it's declared:

function sayHi(toWhom) {    alert("Hi " + toWhom); } sayHi("World!");

In this code, calling the function results in a dialog window with "Hi World!". Barring JavaScript errors, no matter what string is passed to the function or how many times it's called, the same function object is used, and the same result happens: a dialog window opens with a message.

5.1.1.1. A reminder on function naming conventions

Functions do actions. As such, you'll want to incorporate a verb summarizing the activity of the function as much as possible. If you have a hard time naming the function because it's doing more than one task, you may want to consider splitting the function into smaller units, which tends to also encourage reusability.

In fact, the rule should be to keep functions small, specific to a task, and as general as possible. This makes up this chapter's best practice.

JavaScript Best Practice: Keep your functions small, specific to a task, and try to generalize the contained code so that the function can be as reusable as possible.


5.1.2. Function Returns and Arguments

Functions communicate with the calling program through the arguments passed to it and the values returned from it.

Variables based on primitives, such as a string, boolean, or number are passed to a function by value. This means that if you change the actual argument in the function, the change is not reflected in the calling program.

Objects passed to a function, on the other hand, are passed by reference. Changes in the function to the object are reflected in the calling program.

In Example 5-1, two arguments are passed to a function: one is a string variable, the other an array. Both are modified in the function, and then their contents output in the calling program. The string is unchanged, but the array object now has a new value among its members.

Example 5-1. Function arguments, passed as value and by reference

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Pass Me</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <script type="text/javascript"> //<![CDATA[ function alterArgs(strLiteral, aryObject) {        // overwrite original string    strLiteral = "Override";    aryObject[aryObject.length] = "three"; } var str = "Original Literal"; var ary = new Array("one","two"); alterArgs(str,ary); document.writeln("string literal is " + str + "<br /> "); document.writeln("Array object is " + ary); //]]> </script> </body> </html> 

Communication to and from the function is simple: data is passed to a function through one or more arguments; a return statement returns a value from a function to the calling program.

A function may or may not return a value. If it does, the return statement can occur anywhere in the function code, and there could even be more than one return statement. When it encounters a return statement, the JS engine stops processing the function code at that point and returns control to the calling statement.

One reason you might have more than one return statement is if you want to terminate and exit the function when a condition is met. In the following snippet of code, if a condition isn't met in the function, it's terminated immediately; otherwise, processing continues:

function testValues(numValue) { if (isNan(numValue) {     return "error -- not a number"; } ... return ...

Functions don't require return values, though they may be useful in error handlingreturning a value of false if the function isn't successful. (More sophisticated methods of error handling are covered in Chapter 11.)

Opposite in behavior to the declarative function is the dynamic/anonymous function, discussed next.

5.1.3. Anonymous Functions

Functions are objects. As such, they can be createdjust like a String or other typeby using a constructor and assigning the function to a variable. In the following code, a new function is created using the function constructor, function body, and argument passed in as arguments:

var sayHi = new Function("toWhom","alert('Hi ' + toWhom);"); sayHi("World!");

This type of function is often referred to as an anonymous function because the function itself isn't directly declared or named. I know, they are strange-lookingbut that's understandable if you remember that a JavaScript function is an object, and any object can be created dynamically at runtime.

Unlike the declarative function, the JavaScript engine creates the anonymous function dynamically, and each time it's invoked, the function is dynamically reconstructed. If the function is used in a loop, this means it's created with each iteration; a declarative/static function is only created once. As such, you might think anonymous functions aren't too useful. However, a dynamic function is a great way to define the functionality necessary to meet a need that's only determined at runtime.

Here's the syntax of an anonymous function using a constructor:

var variable = new Function ("param1", "param2", ... , "paramn", "function body");

The first parameters are the arguments to the function as they would be defined in a declarative function. The last parameter is the function body. The whole is assigned to a variable:

var func = new Function("x", "y", "return x * y")

This is equivalent to the following using a declarative/static function:

function func (x, y) {    return x * y; }

Example 5-2 takes the dynamic nature of an anonymous function to its extreme. The function body and the value of the two parameters defined for the function are provided by the user via a prompt dialog window. The whole is invoked, and the result is printed out to the page.

Example 5-2. A dynamic/anonymous function

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Build a Function</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <script type="text/javascript"> //<![CDATA[ // prompt for function and args var func = prompt("Enter function body:"); var x = prompt("Enter value of x:"); var y = prompt("Enter value of y:"); // invoke anonymous function var op = new Function("x", "y", func); var theAnswer = op(x, y); // print out results document.writeln("Function is: " + func + "<br />"); document.writeln( "x is: " + x +                  " y is: " + y + "<br />"); document.writeln("The answer is: " + theAnswer); //]]> </script> </body> </html>

Because JavaScript is loosely typed, the function can work with number values:

Function is: return x * y x is: 33 y is: 11 The answer is: 363

It can also work with strings:

Function is: return x + y x is: This is y is: the string The answer is: This is the string

The only requirement is that the operation has to be meaningful for the data type. Even then, a JavaScript error won't happen because the browser doesn't see the error; it happens at runtime. What you'll end up with is something like the following:

Function is: return x * y x is: this is y is: the answers The answer is: NaN

Needless to say, this functionality must be used with caution. I don't recommend allowing your web-page readers to define the functions used within your pages. However, dynamic functions can be an interesting way of dealing with user input, as long as you strip out anything in that input that can cause problems: embedded links, messing around with cookies, calling server-side functionality, creating new functions, etc.

There is another hybrid approach to creating functions that combines the static capabilities of the declarative function with some of the anonymity of the anonymous functions: the function literal, discussed next.

5.1.4. Function Literals

Before introducing the nextand potentially confusingtype of function, a little refresher on objects and literals might be helpful. As demonstrated in earlier chapters, JavaScript objects can have a literal form. Rather than have to use a constructor and the object, you can use a representation. A string can be constructed using the String constructor, and the String methods accessed:

var str = new String("Learning Java"); document.writeln(str.replace(/Java/,"JavaScript"));

You can also use a variable based on the primitive string type and still access the String object's methods; the JavaScript engine implicitly wraps the literal in an object:

var str2 = "Learning Java"; document.writeln(str2.replace(/Java/,"JavaScript"));

In fact, you don't even need a variable:

document.writeln("Learning Java".replace(/Java/,"JavaScript"));

What works for strings also works for functions, which means that you don't have to use a function constructor to create a function and assign it to a variable; it literally becomes a function literal:

var func = (params) { statements; }

Function literals are also known as function expressions because the function is created as part of an expression, rather than as a distinct statement type. They resemble anonymous functions in that they don't have a specific function name. However, unlike anonymous functions, function literals are parsed only once. In fact, other than the fact that the function is assigned to a variable, function literals resemble declarative functions:

var func = function (x, y) {    return x * y; } alert(func(3,3));

Their uniqueness stands out when you extend the concept to do something such as passing a function as a parameter to a function. In Example 5-3, a function, funcObject, is defined, and passes the first two arguments to the third, which is, itself, a function.

Example 5-3. Passing a function to a function

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Pass Me</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <script type="text/javascript"> //<![CDATA[ // invoking third argument as function function funcObject(x,y,z) {    alert(z(x,y)); } // third parameter is function funcObject(1,2,function(x,y) { return x * y}); //]]> </script> </body> </html>

If a function is used within an expression in another statement, it's an example of a function literalno matter what the expression is.

A second form of the function literal isn't anonymous, in that the function is given a name:

var func = function multiply(x,y) {    return x * y; }

However, the name is accessible only from within the function itself. This isn't all that handy, unless you're implementing a recursive function (covered in a later section).

5.1.5. Function Type Summary

To summarize, there are three different function types:


Declarative function

A function in a statement of its own, beginning with the keyword function. Declarative functions are parsed once, static, and given a name for access.


Anonymous function

A function created using a constructor. It's parsed each time it's accessed and is not given a name specifically.


Function literal or function expression

A function created within another statement as part of an expression. It is parsed once, is static, and may or may not be given a specific name. If it is named, the name is accessible only from within the function itself.

Declarative functions are available in all forms of JavaScript, in all browsers. Anonymous functions based on the function constructors are dynamic, memory-intensive, and based on later versions of JS; as such, they may not be available with older browsers. Function literals are later innovations, based in JavaScript 1.5. Only the most modern browsers support these, though the most commonsuch as Mozilla, Firefox, IE, Safari, and othersdo. However, how each of these work with function literals can lead to interesting complications in memory usage, as is examined later in the section on closure.

Function literals also form the basis for most advanced Ajax libraries, as you'll see when we take a closer look at Prototype, Dojo, and other libraries in the last chapters of the book. In addition, function literals, as just demonstrated, are what's used with object event handlers that require callback functions, such as those associated with the Array object.

Windows Freebies

I do most of my web development from my Mac, but from time to time, I develop on my Windows box. One of the advantages to working in Windows is that there seem to be many more JavaScript tools in this environment.

One such is Alban's Script Editor (Version 1.0), formerly known as the Developer's JavaScript Editor. It's described in more detail, including screenshots, at http://www.albantech.com/software/albanxx/. It's an uncomplicated tool that acts as a Notepad replacement and provides syntax highlighting.

Once you're finished writing your web page, you can then compress and obfuscate it with Strong JS, a simple-to-use tool that does both (available at http://www.stronghtml.com/tools/js/index.html). Not only does it compress whitespace, it can also replace variable names with short namesto get that little extra when you really need it.

Firefox isn't the only browser with neat toolbar extensions. Microsoft offers the Internet Explorer Developer Toolbar, which provides most of what you need if you want to peek into a page's inner workings. Because Microsoft changes its URLs frequently, your best bet to find the download site for the Toolbar is to run a search on the term "Internet Explorer Developer Toolbar."

The Toolbar allows you to drill down into the DOM elements on a web page and view the CSS and element attributes, provides a design ruler, and more. You can also test out page resizing, manipulate images, and generally, do most of what you can accomplish with the Firefox Web Developer's toolbar extension.

It's a must for JavaScript developers.





Learning JavaScript
Learning JavaScript, 2nd Edition
ISBN: 0596521871
EAN: 2147483647
Year: 2006
Pages: 151

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net