Team LiB
Previous Section Next Section

Using Functions

Before concluding this chapter, we’ll take a short detour and talk about the practice of using functions in JavaScript. These tips are suggested as good programming practices and should lead to easier-to-maintain code.

Define All Functions for a Script First The reason for this tip should be obvious: we need to make sure a function is defined and read by a browser before we can invoke it. Secondarily, if we define all the functions that our code will use in one place, it makes functions easier to find.

Name Functions Well When naming functions and variables, you need to be a little careful. Because functions and variables share the same namespace, you shouldn’t be declaring variables and functions with the same name. It might be a good idea to precede function names with “func” or some other string or letter of your own choosing. So, using such a scheme, if we had a variable named hello and wanted to define a function also called hello, we would use funcHello.

Note 

Some developers prefer different casing to distinguish between variables and functions, but this may not be obvious enough. The choice is a matter of style and we leave it open for readers to decide for themselves.

Besides the obvious collision of names, very subtle bugs may slip in when we have similar names, particularly when you consider that functions are created when the document is parsed, while variables are created when the script is run. Notice in the following script how there is a variable as well as a function called x.

var x = 5;
function x()
{
 alert("I'm a function!");
}
alert(typeof x);

You might expect the alert to show x to be a function or, more appropriately, an object because it appears to be defined second. However, as you can see here, it is a number:

The output makes sense if you consider when the function and variables are actually created. The function is created as the script is parsed, while the variable gets created as the script runs. While this was a contrived example, it illustrates the importance of understanding how things are created in JavaScript.

Consider Using Linked .js Files for Functions, But Be Cautious While many JavaScript programmers like to put functions in external files, we need to make sure that a function is available before calling it. For example, if we have two .js files (lib1.js and lib2.js), each of which calls functions found in the other, we may have to check to make sure the function is available before calling it because the browser might finish loading one script before the other. In the main document, we would define variables showing the files being loaded as false:

var lib1Loaded = false;
var lib2Loaded = false;

Then, in each of the loaded documents the last line would set the corresponding variables to true. Using this scheme, we would then make sure to look at the value of the variables lib1Loaded or lib2Loaded before any functions that are contained in the files are called. For example:

if (lib1Loaded)
   doSomething(x,y,z)

Most of the time such efforts aren’t required, but JavaScript designers should be careful to consider the load order of documents and what happens if certain parts of a script are invoked before an entire document has loaded.

Use Explicit Return Statements Even if your function will not return any values, insert a return statement anyway. JavaScript being an interpreted language, keeping the interpreter from having to do any extra work or make any assumptions should produce better running scripts.

Write Stand-Alone Functions As always, you should practice modular design and pass data into and out from functions using only function arguments, the return statement, and data values that are passed by reference. We should avoid side-effects such as changing global values from within functions. Local variables should always be used to perform calculations that are unique to a function, and hidden functions can be used in the same manner to create special-purpose functions that are not needed anywhere else. The value of going through the trouble to create stand-alone functions in this fashion is that such functions can be reused without worry in a variety of situations.

Check Arguments Carefully As we have seen, JavaScript doesn’t carefully check the number or type of variables passed to a function. It is possible to use variadic functions, functions that accept a variable number of arguments, to write very powerful code. However, it is equally possible that doing so will cause a problem. For example, consider this simple function that does no checking:

function addTwoNumbers(x,y)
{
 alert(x+y);
}
addTwoNumbers(5);

This could be easily rewritten to check for the number of arguments passed:

function addTwo(x,y)
{
 if (addTwo.arguments.length == 2)
   alert(x+y);
}

Of course, this wouldn’t correct a bad function call like

addTwo(5,true);

which would produce a value of 6, since true would be converted to the integer 1. If we added type-checking into our function, we could solve this problem, as shown here:

function addTwo(x,y)
{
 if (addTwo.arguments.length == 2) 
 {
   if ( (typeof(x) != "number") || (typeof(y) !="number") )
     return;
   else 
     alert(x+y);
 }
return;
}

As we can see, to create truly reusable functions that will withstand anything thrown at them, we will have to put in some more effort.

Comment Your Functions Consider putting a comment block before a function indicating the name of the function, its purpose, the number and type of parameters accepted, any return values, and any output the function may produce. An example of such a comment block is shown here:

/* 
  Function customAlert(message,icon,color,buttontext) 

  Description: This function creates a custom alert dialog
               with passed message, icon, color and buttontext. 

  Input:  message - a string containing message to be displayed
          icon - reference to a GIF or JPEG image to be used on dialog
          color - default color in the form of a hex color 
                  string to be used for background. White is used
                  if unspecified
          buttontext - string containing message to be used on
                       dialog button.  Uses the string "ok" if
                       unspecified.

 Output: creates a dialog window relative to the current window
         returns true if successful in creating window, false otherwise
*/ 
function customAlert(message, icon, color, buttontext)
{
  // function goes here
}

Unfortunately, few JavaScript programmers document their functions this way, probably because of the concern of the extra size for download. Of course, we could always have such code stripped down to the bare essentials using a tool before uploading to a Web site, but such practices are still relatively rare.

Good programming is not just a matter of correct syntax, but also consistent style. Many may argue about the benefits of one particular coding style over another, but whatever you choose, stick to it. In this chapter we have shown a primarily modular programming style that should be familiar to anyone who has programmed in Pascal or C. However, a more modern programming style based upon object usage is also possible and is used in the next chapter.


Team LiB
Previous Section Next Section