JavaScript Editor JavaScript Debugger     JavaScript Editor 



Team LiB
Previous Section Next Section

Functions as Objects

As we’ll see in the next chapter, in JavaScript just about everything that is not primitive data is an object, and functions are no exception. Thus, it is possible to define functions in a much different way than we have seen up until now, by using the keyword new and the Function object. For example, here we define a function and assign it to the variable sayHello. Notice that Function is capitalized, as we are talking about creating an instance of JavaScript’s built-in Function object:

var sayHello = new Function("alert('Hello there');");

Later on we can then use the assigned variable sayHello just like a regular function call:

sayHello();

Because functions are first-class data types, the function can even be assigned to another variable and used by that name instead.

var sayHelloAgain = sayHello;
sayHelloAgain();

To expand the example, we could define a function with a parameter to print out

var sayHello2 = new Function("msg","alert('Hello there '+msg);");

and call it:

sayHello2('Thomas');

The general syntax for the Function() constructor is

var functionName = new Function("argument 1",..."argument n", 
"statements for function body");

As we have already seen, functions can have zero arguments, so the actual number of parameters to Function() will vary. The only thing we have to do is pass, as the final argument, the set of statements that are to execute as the body of the function.

If you have coded JavaScript before, you may not have seen this style of function definition and might wonder what its value is. The main advantage of declaring a function using the new operator is that a script can create a function after a document loads.

Note 

Since JavaScript 1.2, you can create functions using new anywhere in the script; previously, you could only define them globally and not within a block such as those associated with if statements, loops, or other functions.

Function Literals and Anonymous Functions

As we have seen in the previous section, defining a function using a new operator doesn’t give the function a name. A similar way to define a function without a name and then assign it to something is by using a function literal. Function literals use the function keyword but without an explicit function name.

A simple use of a function literal is

var sayHi = function(name) { alert('Hi my name is '+name); };
sayHi('Fritz');

We assign a function literal to sayHi and can then use it as we would any other function.

The previous example wasn’t particularly compelling, but function literals do have their uses. Their primary use is when creating methods for user-defined objects. A simple example showing function literals used in this manner is presented here. We have defined a function SimpleRobot that is used as an object constructor—a function that creates an object. Within the function we have defined three methods that are assigned function literals.

function SimpleRobot(robotName)
{
   this.name = robotName;
   this.sayHi = function () { alert('Hi my name is '+this.name); };
   this.sayBye = function () { alert('Bye!'); };
   this.sayAnything = function (msg) { alert(this.name+' says '+msg); };
}

It is now simple to create an object using the new operator in conjunction with our SimpleRobot constructor function, as shown here:

var fred = new SimpleRobot("Fred");

Invoking the various functions, or, more correctly, methods, is simply a matter of invoking their names, similar to plain function calls:

fred.sayHi();
fred.sayAnything("I don't know what to say");
fred.sayBye();

The result of the previous example is shown here:

You might wonder why not just use the following new-style syntax in the constructor function:

function SimpleRobot(robotName)
{
   this.name = robotName;
   this.sayHi = new Function ("alert('Hi my name is '+this.name); ");
   this.sayBye = new Function ("alert('Bye!'); ");
   this.sayAnything = new Function("msg","alert(this.name+' says '+msg);" );
}

The reality is you could, and everything would still operate properly. The only downside to this approach is that it might use substantially more memory, as new function objects are created every time you create a new object.

A similar kind of nameless function doesn’t even get assigned a name at any time. An anonymous function is one that cannot be further referenced after assignment or use. For example, we may want to sort arrays in a different manner than what the built-in sort() method provides (as we’ll see in Chapter 7); in such cases, we may pass an anonymous function:

var myArray = [2, 4, 2, 17, 50, 8];
myArray.sort( function(x, y) 
              { 
               // function statements to do sort
              }
             );

The creation of an anonymous function is in this case carried out by using a function literal. While the function is accessible to sort() because it was passed a parameter, the function is never bound to a visible name, so it is considered anonymous.

Anonymous functions may be confusing, so you probably won’t need to use them very often, if at all. Probably the only other place they are used in JavaScript is with event handlers, as shown here:

<<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">>
<<html xmlns="http://www.w3.org/1999/xhtml">>
<<head>>
<<title>>Simple Event and Anonymous Function<</title>>
<<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />>
<</head>>
<<body>>
<<form id="form1" name="form1">>
      <<input type="button" id="button1" name="button1" value="Press me" />>
<</form>>
<<script type="text/javascript">>
 window.document.form1.button1.onclick = function () {alert('The button 
was pressed!')};
<</script>>
<</body>>
<</html>>

The use of anonymous function with events is also discussed in Chapter 11.

Static Variables

One interesting aspect of the nature of functions as objects is that you can create static variables. A static variable is a variable in a function’s local scope whose value persists across function invocations. Creating a static variable in JavaScript is achieved by adding an instance property to the function in question. For example, consider the code here that defines a function doSum that adds two numbers and keeps a running sum:

function doSum(x, y)               
{
    doSum.totalSum = doSum.totalSum + x + y;    // update the running sum
    return(doSum.totalSum);                     // return the current sum
}

// Define a static variable to hold the running sum over all calls
doSum.totalSum = 0;

document.write("First Call = "+doSum(5,10)+"<<br />>");
document.write("Second Call = "+doSum(5,10)+"<<br />>");
document.write("Third Call = "+doSum(100,100)+"<<br />>");

The result shown next demonstrates that by using a static variable we can save data between calls of a function.

Click To expand

If you need to keep values from one invocation to another, static variables should be strongly preferred to using global variables.

Advanced Parameter Passing

As objects, user-defined JavaScript functions have a variety of properties and methods associated with them. One particularly useful property is the read-only length property that indicates the number of parameters the function accepts. In this example,

function myFunction(arg1,arg2,arg3)
{
  // do something 
}
alert("Number of parameters expected for myFunction = "+myFunction.length);

the script would show that myFunction takes three parameters. Since this property shows the defined parameters for a function, when a function is declared as taking no arguments, a value of 0 is returned for its length property.

Note 

Netscape 4.x and greater browsers also support an arity property that contains the same information as length. Because this is nonstandard, it should be avoided.

Of course, it is possible to vary the number of arguments actually given to a function at any time, and we can even accommodate this possibility by examining the arguments[] array associated with a particular function. This array is implicitly filled with the arguments to a function when it is invoked. The following example shows a function, myFunction, that has no defined parameters but that is called with three arguments:

function myFunction()
{
 document.write("Number of parameters defined = "+myFunction.length+"<<br/>>");
 document.write("Number of parameters passed = "+myFunction.arguments.length+
"<<br />>")
 for (i=0;i<<arguments.length;i++)
   document.write("Parameter "+i+" = "+myFunction.arguments[i]+"<<br />>")
}
myFunction(33,858,404);

The result shown here indicates that JavaScript functions are perfectly happy to receive any number of parameters.

Click To expand

Of course, you may wonder how to put this to use. The following example shows a summation routine that adds any number of arguments passed to it:

function sumAll()
{
  var total=0;

  for (var i=0; i<<sumAll.arguments.length; i++)
    total+=sumAll.arguments[i];
  return(total);
}
alert(sumAll(3,5,3,5,3,2,6));

Note that this isn’t a terribly robust function—if you pass it strings or other data types that shouldn’t be added, it will try to sum those as well. We’ll see more sophisticated uses of functions taking a variable number of parameters when we present various JavaScript applications later in the book. We will also see functions used as objects starting in the next chapter. For now, let’s turn our attention to a special technique used in creating functions—recursion.


Team LiB
Previous Section Next Section


JavaScript Editor JavaScript Debugger     JavaScript Editor


©