Chapter 6. Building Reusability with JavaScript Functions

6.0. Introduction

JavaScript functions provide a way to encapsulate a block of code in order to reuse the code several times. They’re typically created using the function statement and syntax similar to the following:

function functionname(arg1, arg2, ..., argn) {
   function body
}

JavaScript functions have Function objects, which can be constructed the same as a String or Number, using the new operator:

var fn = new Function (arg1, arg2, ..., argn, functionbody);

However, using this syntax is not as efficient as using the function statement, because using a function constructor requires that the function be parsed each time it’s called. Functions defined with the function statement are parsed once, when the code is loaded.

There are three basic kinds of functions:

Declarative function

A declarative function is a statement triggered by the use of the function keyword, and parsed when the JavaScript application is first loaded.

Anonymous function or function constructor

An anonymous function is constructed using the new operator and referencing the Function object. It’s anonymous because it isn’t given a name, and access to the function occurs through a variable or another object property. It’s parsed each time it’s accessed.

Function literal or function expression

As with other JavaScript objects, functions can be both object and literal. A literal function is a function expression, including parameter and body, which is used in place—such as in an argument to another function. Like a declarative function, it’s also parsed only once, when the JavaScript application is loaded. Like the function created as an object, it can also be anonymous.

6.1. Creating a Block of Reusable Code

Problem

You want to create a block of code that you can use several times.

Solution

Create a simple, named, parameter-less function using the function statement:

function simpleFunction() {
   alert("Hello, function!");
};

simpleFunction();

Discussion

A function created using the function keyword and given a name is known as both a declarative function and a static function. The basic structure is:

function functionName() {
   // JavaScript statements
}

This type of function is parsed when the page containing the JavaScript application is loaded, and the parsed results are used whenever the function name is referenced. It’s an efficient way of reusing the same code.

Any name that would be valid for a variable would work for a function. Variable names can be any combination of characters, numbers, and underscores, as long as the variable name starts with a character or underscore and case-sensitivity is preserved.

However, functions typically perform some action, and best practices suggest that the function name should be descriptive. For instance, a function that sums the numbers in an HTML table might be named sumTableValues.

6.2. Passing Single Data Values to and from a Function

Problem

You need to pass data values into a named function and get a result back.

Solution

Provide arguments for the incoming data, and return the result:

function makeHello(strName) {
   return ("Hello " + strName);
}

window.onload=function() {
   var name = prompt("What's your name?","");
   var greeting = makeHello(name);
   alert(greeting);
}

Discussion

Function arguments are a way to pass data to a function. The arguments are separated by commas and included in the parentheses following the function name:

var firstName = "Shelley":
var lastName = "Powers";

makeHello(firstName, lastName);

The function then processes the arguments, as needed:

function makeHello(firstName, lastName) {
    alert("Hello " + firstName + " " + lastName);
}

Data is returned from the function to the calling program using the return statement:

function makeHello(firstName, lastName) {
   return "Hello " + firstName + " " + lastName;
}

You can pass several arguments to the function, but only one return value. If you want to return more than one value, you can pass more complex objects, such as an array, to and from a function.

Unless you’re sure about the type of data coming from the user, you’ll want to also test the data first. For instance, if you want to ensure that a value passed to the function is a number, you could do the following:

function someFunc(num) {
   if (typeof num == "number") {
      ...
   }
}

You also don’t have to provide a one-to-one mapping between the value passed to the object, and the number of function parameters. Every function has an arguments object which contains all of the arguments passed to the function. It’s not a true function, but you can use array index notation to access the argument, and it does provide a length property for the number of arguments:

function sumNums() {
  var sum = 0;
  for (var i = 0; i < arguments.length; i++) {
     var num = parseFloat(arguments[i]);
     if (!isNaN(num)) {
        sum+=num;
     }
   }
   return sum;
}
...
var sum = sumNums(4.55, 3.0,1, "apple", 56.33);

See Also

Recipe 6.3 demonstrates passing more complex objects as arguments.

6.3. Passing Complex Data Objects to a Function

Problem

You need to pass more complex data to a function.

Solution

You can use objects, such as arrays, as function arguments:

function makeHello(name) {
   name[name.length] = "Hello " + name[0] + " " + name[1];
}
var name = new Array('Ima','Reader');
makeHello(name);
alert(name[2]); // displays "Hello Ima Reader"

Discussion

Function arguments in JavaScript can be scalar values, such as a string or number, or complex objects, such as arrays. Arrays are a simple way to pass many values to a function without having to create separate parameters for each. It’s also a way to pass an unknown number of values to a function, such as an array of numbers to be summed:

function addNumbers(nums) {
   var total = 0;
   for (var i = 0; i < nums.length; i++) {
      total+=nums[i];
   }
   return total;
}

A complex object is treated differently than a scalar argument in a function. In the solution, an array is passed to the makeHello function, but isn’t returned from the function. However, the generated value added to the array in the function is still accessible to the calling program, because objects are passed into functions by reference.

Scalar arguments are passed by value, which means that a copy of the argument is made for processing in the function and changes to the argument in the function won’t be reflected back to the calling program. Objects, though, are passed by reference: any changes to them in the function are reflected in the calling program.

Example 6-1 demonstrates the differences between scalar and complex objects when used as function arguments. The function takes two parameters, a string literal and an array. Both are modified in the function, and the contents of both are printed after the function returns control to the calling program.

Example 6-1. Functional differences between scalar and array arguments
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Function test</title>
<script>
//<![CDATA[

window.onload=function() {
  var items = new Array('apple','orange','cherry','lime');
  var sep = '*';
  concatenateString(items,sep);

  alert(items);
  alert(sep);
}

function concatenateString(strings, separator) {
  var result="";
  for (var i = 0; i < strings.length; i++) {
    result+=strings[i] + separator;
  }

  // assign result to separator
  separator = result;

  // and array
  strings[strings.length]=result;
}


//--><!]]>
</script>
</head>
<body>
</body>
</html>

The array reflects the change that occurred in the function:

apple,orange,cherry,lime,apple*orange*cherry*lime*

While the string argument does not reflect the change, and consists only of the asterisk separator string (*).

6.4. Creating a Dynamic Runtime Function

Problem

You need to create a function, but you won’t know its structure until runtime.

Solution

Use an anonymous function, created using the Function object constructor:

// two parameters and one function body string
var functionName = new Function (x, y, functionBody);
functionName(varA, varB); // two parameters are processed by function

Discussion

Functions created using the new Function object constructor are called anonymous functions because they’re not given a function name when they’re created. Instead, they’re assigned to a variable. You then use the variable as you would a function call.

Anonymous functions are parsed at runtime, which makes them inefficient for general purposes. However, they allow us to define both parameters and function body at runtime, which is handy if you’re not sure what the function body is going to be until runtime.

To demonstrate an anonymous function, I’m going to borrow an example from another of my books, Learning JavaScript (O’Reilly), replicated in Example 6-2. This JavaScript application prompts the web page reader to provide a function that takes two parameters, as well as the value of the parameters. The application then uses these values to create the function and invoke it.

Example 6-2. Using an anonymous function
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Anonymous Function</title>
<script>
//<![CDATA[

window.onload=function() {

  var func = prompt("Enter function body:","");
  var x = prompt("Enter value for x:","");
  var y = prompt("Enter value for y:","");

  var newFun = new Function("x","y",func);
  var result = newFun(x,y);

}


//--><!]]>
</script>
</head>
<body>
</body>
</html>

When prompted for the function body, use something simple such as this (shown in Figure 6-1):

alert(x + " " + y)

If you pass in Hello and World for the next two prompts, the result is an alert message with “Hello World”.

Entering function body for anonymous function
Figure 6-1. Entering function body for anonymous function

The function return value is assigned a variable, just in case the dynamic function body returns a value. If no value is returned, then the returned value is undefined.

Of course, using an anonymous function like this isn’t the safest thing to do, because you can’t control what the person enters as function body. And it’s not particularly useful either.

Anonymous functions can be useful when passing functions as arguments, or assigning them to object properties. However, in most of these cases a literal function is preferred over a function object, because function literals are parsed once, when the application is loaded.

See Also

Literal functions are covered in Recipe 6.5.

6.5. Passing a Function As an Argument to Another Function

Problem

You want to pass a function as an argument to another function.

Solution

For the following function:

function otherFunction(x,y,z) {
  x(y,z);
}

use a literal function:

var param = function(arg1, arg2) { alert(arg1 + " " + arg2); };
otherFunction(param, "Hello", "World");

or a function expression as a function argument:

otherFunction(function(arg1,arg2) { alert(arg1 + ' ' + arg2); }, "Hello","World");

Discussion

The function keyword is an operator as well as a statement, and can be used to create a function as an expression. Functions created this way are called function expressions, function literals, and anonymous functions, though “anonymous functions” is an overloaded term since it applies to functions as objects, as well as functions as expressions.

A function name can be provided with literal functions, but it’s only accessible within the function:

var param = function inner() { return typeof inner; }
alert(param()); // prints out "function"

This functionality may not seem useful, but it’s essential if you want to implement recursion.

You can pass a function as an argument to another function as a named variable, or even directly within the argument list, as shown in the solution. Unlike functions constructed as objects, function literals are parsed when the page is loaded, rather than each time they’re accessed.

See Also

See Recipe 6.6 for a demonstration of using a named function literal in recursion.

6.6. Implementing a Recursive Algorithm

Problem

You want to implement a function that will recursively traverse an array and return a reversed array string.

Solution

Use a function literal recursively until the end goal is met:

 var reverseArray = function(x,indx,str) {
   return indx == 0 ? str : reverseArray(x,--indx,(str+= " " + x[indx]));;
}

 var arr = new Array('apple','orange','peach','lime');
 var str = reverseArray(arr,arr.length,"");
 alert(str);

 var arr2 = ['car','boat','sun','computer'];
 str = reverseArray(arr2,arr2.length,"");
 alert(str);

Discussion

Before looking at the solution, I want to cover the concept of recursion first, and the look at functional recursion.

Recursion is a well-known concept in the field of mathematics, as well as computer science. An example of recursion in mathematics is the Fibonacci Sequence:

fn = fn-1 + fn-2, for n= 2,3,4,...,n and f0 = 0 and f1 = 1

A Fibonacci number is the sum of the two previous Fibonacci numbers.

Another example of mathematical recursion is a factorial, usually denoted with an exclamation point (4!). A factorial is the product of all integers from 1 to a given number n. If n is 4, then the factorial (4!) would be:

24 = 1 × 2 × 3 × 4

These recursions can be coded in JavaScript using functional recursion. A common example of JavaScript recursion is the solution for a Fibonacci:

var fibonacci = function (n) {
   return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}

or a factorial:

function Factorial(n) {
   return n == 1 ? 1 : n * Factorial(n -1);
}
var val = Factorial(4);

In the Fibonacci example, n is tested to see if it is less than 2. If it is, the value of n (2) is returned; otherwise the Fibonacci function is called again with (n – 1) and with (n – 2), and the sum of both is returned.

A little convoluted? The second example with the Factorial might be clearer. In this example, when the function is first called, the value passed as argument is compared to the number 1. If n is less than or equal to 1, the function terminates, returning 1.

However, if n is greater than 1, what’s returned is the value of n times a call to the Factorial function again, this time passing in a value of n – 1. The value of n, then, decreases with each iteration of the function, until the terminating condition (or base) is reached.

What happens is that the interim values of the function call are pushed onto a stack in memory and kept until the termination condition is met. Then the values are popped from memory and returned, in a state similar to the following:

return 1;

// 0!

return 1;

// 1!

return 1 * 2;

// 2!

return 1 * 2 * 3;

// 3!

return 1 * 2 * 3 * 4;

// 4!

In the solution, we reverse the array elements by using a recursive function literal. Instead of beginning at index zero, we begin the array from the end length, and decrement this value with each iteration. When the value is zero, we return the string.

If we want the reverse, to concatenate the array elements, in order, to a string, we modify the function:

 var orderArray = function(x,indx,str) {
  return indx == x.length-1 ? str : orderArray(x,++indx,(str+=x[indx] + " "));
}

var arr = new Array('apple','orange','peach','lime');
var str = orderArray(arr,-1,"");

Rather than the length of the array, we start with an index value of –1, and continue the loop until one less than the length of the array. We increment the index value, rather than decrement with each loop.

Most recursive functions can be replaced with code that performs the same function linearly, via some kind of loop. The advantage of recursion is that recursive functions can be fast, and efficient. The downside, though, is that recursive functions can be very memory-intensive.

See Also

Some of the negative consequences of recursive functions can be mitigated via memoization, covered in Recipe 6.9. Accessing the outer variable internally with the recursive function is covered in Recipe 6.7, which goes into function scope.

6.7. Create a Function That Remembers Its State

Problem

You want to create a function that can remember static data, but without having to use global variables and without resending the same data with each function call.

Solution

Create an outer function that takes one or more parameters, and then an inner function that also takes one or more parameters but uses both its and its parent function’s parameters in order to perform its functionality. Return the inner function from the outer function, and assign it to a variable. From that point, use the variable as a function:

function greetingMaker(greeting) {
   function addName(name) {
      return greeting + " " + name;
   }
   return addName;
}

// Now, create new partial functions
var daytimeGreeting = greetingMaker("Good Day to you");
var nightGreeting = greetingMaker("Good Evening");

...

// if daytime
alert(daytimeGreeting(name));

// if night
alert(nightGreeting(name));

Discussion

We want to avoid global variables as much as possible because of potential clashes between libraries. However, there are times when you need to store data to be used across several function calls, and you don’t want to have to repeatedly send this information to the function each time.

A way to persist this data from one function to another other is to create one of the functions within the other, so both have access to the data, and then return the inner function from the outer. Returning one function from another is known as a function closure. Before I get into the specifics of function closure, I want to spend a few minutes on functions and scope.

Note

This type of function closure is also known as a partial function, or currying, which is covered in detail in Recipe 6.8.

In the solution, the inner function addName is defined in the outer function greetingMaker. Both of the functions have one argument. The inner function has access to both its argument and the outer function’s argument, but the outer function cannot access the argument passed to the inner function. The inner function can operate on the outer function’s parameters because it is operating within the same context, or scope, of the outer function.

In JavaScript, there is one scope that is created for the outermost application environment. All global variables, functions, and objects are contained within this outer scope.

When you create a function, you create a new scope that exists as long as the function exists. The function has access to all variables in its scope, as well as all of the variables from the outer scope, but the outer scope does not have access to the variables in the function. Because of these scoping rules, we can access window and document objects in all of our browser applications, and the inner function in the solution can also access the data passed to, or originating in, the outer function that wraps it.

Note

This also explains how the recursive functions in Recipe 6.6 can internally access the variables they’re assigned to in the outer application scope.

However, the outer function cannot access the inner function’s arguments or local data, because they exist in a different scope.

An inner function doesn’t have to be returned from the outer function. It could be an invoked direction in the code in the outer function. When it is returned, like in the solution, and the following code:

function outer (x) {
  return function(y) { return x * y; };
}

var multiThree = outer(3);
alert(multiThree(2)); // 6 is printed
alert(multiThree(3)); // 9 is printed

the returned function forms a closure. A JavaScript closure is a variable local to a function that remains alive when the function returns.

When the inner function is returned from the outer function, its application scope at the time, including all references to the outer function’s variables, is now passed to the outer, global scope. So even though the outer function’s application scope no longer exists, the inner function’s scope exists at the time the function was returned, including a snapshot of the outer function’s data. It will continue to exist until the application is finished, and the outer, global scope is released.

Note

Another way a closure can be made is if an inner function is assigned to a global variable.

So what happens to these variables when an application scope is released? JavaScript supports automatic garbage collection. What this means is you and I don’t have to manually allocate or deallocate memory for our variables. Instead, the memory for variables is created automatically when we create variables and objects, and deallocated automatically when the variable scope is released.

In the solution, the outer function greetingMaker takes one argument, which is a specific greeting. It also returns an inner function, addName, which itself takes the person’s name. In the code, greetingMaker is called twice, once with a daytime greeting, assigned to a variable called daytimeGreeting, and once with a nighttime greeting, assigned to a variable called nightGreeting.

Now, whenever we want to greet someone in daytime, we can use the daytime greeting function, daytimeGreeting, passing in the name of the person. The same applies to the nighttime greeting function, nightGreeting. No matter how many times each is used, the greeting string doesn’t need to be respecified: we just pass in a different name. The specialized variations of the greeting remain in scope until the page that contains the application is unloaded from the browser.

Closures are interesting and useful, especially when working with JavaScript objects, as we’ll see later in the book. But there is a downside to closures that turns up when we create accidental closures.

An accidental closure occurs when we code JavaScript that creates closures, but aren’t aware that we’ve done so. Each closure takes up memory, and the more closures we create, the more memory is used. The problem is compounded if the memory isn’t released when the application scope is released. When this happens, the result is a persistent memory leak.

Here’s an example of an accidental closure:

function outerFunction() {
   var doc = document.getElementById("doc");
   var newObj = { 'doc' : doc};
   doc.newObj = newObj;
}

The newObj contains one property, doc, which contains a reference to the page element identified by doc. But then, this element is given a new property, newObj, which contains a reference to the new object you just created, which in turn contains a reference to the page element. This is a circular reference from object to page element, and page element to object.

The problem with this circular reference is exacerbated in earlier versions of IE, because IE does not release memory associated with DOM objects (such as the doc element) if application scope is released. Even leaving the page does not reclaim the memory: you have to close the browser.

Note

Other browsers detected this type of situation and performed a cleanup when the user left the application (the web page where the JavaScript resided).

Luckily, newer versions of IE don’t have this problem. However, function closures should be deliberate, rather than accidental.

See Also

More on function closures and private function methods in Chapter 16. An excellent overview of function scope and closure is “JavaScript Closures”, by Richard Cornford. Though written in 2004, it’s still one of the best descriptions of closures. Mozilla provides a nice, clean description of closures at https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Working_with_Closures.

Recipe 6.8 also makes use of specialized function closure, specifically for simplifying the number of arguments that have to be passed to functions, an effect called currying.

6.8. Improving Application Performance with a Generalized Currying Function

Problem

You have several functions you want to simplify by attaching recurring argument values to the functions, so the arguments don’t have to be repeated.

Solution

Use the concept of currying, a specialized form of function closure, to create a function generator that takes the function name and the persisted arguments, and returns a new partial function that only needs the remaining arguments. Here is the curry function I adapted from a function created by Dustin Diaz, which works in all of this book’s target browsers:

function curry (fn, scope) {
    var scope = scope || window;
    var args = [];
    for (var i=2, len = arguments.length; i < len; ++i) {
        args.push(arguments[i]);
    };
    return function() {
        var args2 = [];
        for (var i = 0; i < arguments.length; i++) {
            args2.push(arguments[i]);
         }
         var argstotal = args.concat(args2);
         return fn.apply(scope, argstotal);
    };
}

When you want to curry a function, you pass the function name, and whatever values you want statically assigned to the returned function:

function diffPoint (x1, y1, x2, y2) {
   return [Math.abs(x2 - x1), Math.abs(y2 - y1)];
}
var diffOrigin = curry(diffPoint, null, 3.0, 4.0);
var newPt = diffOrigin(6.42, 8.0); // array with 3.42, 4

Discussion

A typical function could be like the following, which takes two pairs of numbers (an origin and a new location) and returns an array with the difference between the two:

function diffPoint (x1, y1, x2, y2) {
  return [x2 - x1, y2 - y1];
}

The function is fine, but if the origin is going to be the same across many calls to the function, wouldn’t it be nice to somehow attach this information to the function? Currying is the process that allows us to do this.

Currying is a way of statically attaching more than one argument to a function, so the argument doesn’t have to be duplicated. We demonstrated one form of currying in Recipe 6.7, but in that case, we created a single purpose outer function in order to provide the currying functionality for the inner function.

In the solution, what I’ve done is create a multipurpose currying function that can perform this functionality for any method in which we want to split parameters between those repeated and those not. In the curry method, I capture the arguments for the first function call, and those from the second, concatenate the two, and then use the Function apply method to return a function with the combined set of arguments.

The code then uses the curry method to create a new function, diffOrigin, that finds the difference between the point and a given origin, in this case, where origin is at x = 3, y = 4:

var diffOrigin = curry(diffPoint, null, 3.0, 4.0);
var newPt = diffOrigin(6.42, 8.0); // array with 3.42, 4

We can use the same curry method with diffPoint and another set of origin points:

var farPoint = curry (diffPoint, null, 183.66, 98.77);

and then use it as many times as needed:

var ptA = farPoint(1.33, 2.11);
var point0 = genFunction(0,0);  // 182.329999..., 96.66

The curry method can also take a scope as an argument. In the example, there is no specialized scope, so the window object is used. However, I could also have passed in a reference to an element or other object, and then the inner function would have access to that object’s context.

See Also

A curry method is provided in many JavaScript libraries, such as Dojo, jQuery, and Prototype.js, either directly or as an extension. The Function apply method is demonstrated in Chapter 16, beginning with Recipe 16.5. See another example of function closure and currying in Recipe 6.7.

6.9. Improve Application Performance with Memoization (Caching Calculations)

Problem

You want to optimize your JavaScript applications and libraries by reducing the need to repeat complex and CPU-intensive computations.

Solution

Use function memoization in order to cache the results of a complex calculation. Here, I’m borrowing an example from Douglas Crockford’s book, JavaScript: The Good Parts (O’Reilly), as applied to the code to generate a Fibonacci number:

var fibonacci = function () {
   var memo = [0,1];
   var fib = function (n) {
      var result = memo[n];
      if (typeof result != "number") {
    result = fib(n -1) + fib(n - 2);
     memo[n] = result;
      }
      return result;
   };
   return fib;
}();

Discussion

Memoization is the process where interim values are cached, rather than recreated, cutting down on the number of iterations and computation time. It works especially well with something like the Fibonacci numbers, or factorials, both of which operate against previously calculated values. For instance, we can look at a factorial, 4!, as follows:

return 1;

// 0!

return 1;

// 1!

return 1 * 2;

// 2!

return 1 * 2 * 3;

// 3!

return 1 * 2 * 3 * 4;

// 4!

But we can also view it as:

3! * 4 // 4!

In other words, if we cache the value for 2! when creating 3!, we don’t need to recalculate 1 * 2; and if we cache 3! when calculating 4!, we don’t need 1 * 2 * 3, and so on.

Memoization is built into some languages, such as Java, Perl, Lisp, and others, but not into JavaScript. If we want to memoize a function, we have to build the functionality ourselves. The key to the effective use of memoization is being aware that the technique doesn’t result in performance improvements until the number of operations is significant enough to compensate for the extra effort.

Example 6-3 shows the memoized and nonmemoized versions of the Fibonacci function that Crockford provided in his book. The example also uses the Console API to record times, so you’ll need to run the application in Firefox or Safari. Make sure the tool’s Console is open. Note that the calculations are intense and can take a considerable time. Save any work you have in other tabs. You may have to override a message given by the browser, too, about killing a script that’s running a long time.

Example 6-3. A demonstration of memoization
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Testing Memoization</title>
<script>
//<![CDATA[

window.onload=function() {

// Memoized Function
var fibonacci = function () {
   var memo = [0,1];
   var fib = function (n) {
      var result = memo[n];
      if (typeof result != "number") {
          result = fib(n -1) + fib(n - 2);
          memo[n] = result;
      }
      return result;
   };
   return fib;
}();

// nonmemoized function
var fib = function (n) {
   return n < 2 ? n : fib(n - 1) + fib(n - 2);
};
// run nonmemo function, with timer
console.time("non-memo");
for (var i = 0; i <= 10; i++) {
   console.log(i + " " + fib(i));
}
console.timeEnd("non-memo");

// now, memo function with timer
console.time("memo");
for (var i = 0; i <= 10; i++) {
   console.log(i + " " + fibonacci(i));
}
console.timeEnd("memo");

}
//--><!]]>
</script>
</head>
<body>
<p>content</p>
</body>
</html>

First, the code is run against a number of 10. The result is as follows, and as shown in Figure 6-2:

non-memo: 39ms
memo: 38ms
Memoization program running in Safari, with debugger and console displayed
Figure 6-2. Memoization program running in Safari, with debugger and console displayed

The result generates one big “meh.” In the second run, though, the code is edited to run the code in a for loop of 30. The result is as follows:

non-memo: 54761ms
memo: 160ms

A major change.

See Also

There’s little information on JavaScript memoization online. There has been effort to create memoize functions that can work with all functions that would benefit. Crockford provided one in his book, JavaScript: The Good Parts (O’Reilly). Other discussions on the topic can be found by searching for “JavaScript memoization” in your favorite search engine.

6.10. Using an Anonymous Function to Wrap Global Variables

Problem

You need to create a variable that maintains state between function calls, but you want to avoid global variables.

Solution

Use an anonymous function to wrap variables and functions both:

<!DOCTYPE html>
<head>
<title>faux Global</title>
<script>

(function() {
  var i = 0;

  function increment() {
    i++;
    alert("value is " + i);
  }

  function runIncrement() {
    while (i < 5) {
      increment();
    }
  }

  window.onload=function() {
    runIncrement();
  }
})();

</script>
</head>
<body>
</body>

Discussion

The functionality demonstrated in the solution has existed for some time, but I’ve only seen anonymous functions as a way to scope what would normally be global variables in John Resig’s work with the jQuery framework library. It’s used as a way of wrapping jQuery plug-in functions so that the code can use the jQuery dollar sign function ($) when the jQuery plug-in is used with another framework library, such as Prototype, which also uses the dollar sign function:

// swap colors, blue and red
(function($) {
    $.fn.flashBlueRed = function() {
       return this.each(function() {
         var hex = $.bbConvertRGBtoHex($(this).css("background-color"));
         if (hex == "#0000ff") {
             $(this).css("background-color", "#ff0000");
          } else {
             $(this).css("background-color", "#0000ff");
          }
        });
    };
})(jQuery);

The approach consists of surrounding the code block with parentheses, beginning with the anonymous function syntax, and following up with the code block and then the final function closure. It could be the following, if there’s no parameter passed into the code block:

})();

or the following, if you are passing a parameter into the function:

})(jQuery);

Now you can use as many “global” variables as you need without polluting the global space or colliding with global variables used in other libraries.

See Also

Recipe 17.7 covers writing jQuery plug-ins.

Get JavaScript Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.