Functional Javascript

Harnessing the Power of the Function Object

Rob Gravelle
JavaScript is a language that operates on many levels. Everyone who writes JavaScript learns early on to separate code by function in order to avoid repetition. This style of programming is known as Procedural Programming because procedures (functions) are used to group similar functionality. JavaScript also supports most of the features of the Object-Oriented paradigm such as encapsulation, modularity, polymorphism, and inheritance. Perhaps not a pure OO language like Java, the proliferation of JavaScript Frameworks in recent years, as well as the inclusion of new functionality in later versions of JavaScript, have brought the language ever closer to true OO style. In this article, we'll explore the Function Object and learn about its role in a lesser known style of coding called Functional Programming. Ironically, JavaScript may very well be the most widely deployed Functional Programming language in use today, but most people are blissfully unaware of this fact. That's a shame, because the Functional Programming style is one of our best allies in writing well-structured and modularized code.

Functional Programming: What It's All About

Lets begin by stating what Functional Programming is, since you may well have never heard of it. Simply put, it's a style of programming that emphasizes the evaluation of expressions rather than the execution of commands. Tracing back to calculus mathematics, the main goal of Functional Programming is to prevent the inadvertent changing of already calculated values. As developers know all too well, the most likely cause of accidental variable modifications are functions that have access to global objects. The reason that the accessing of global variables by multiple functions is inherently dangerous is that changing a global variable in part of a program can have unexpected effects in another part. Functional programming is not a replacement for Object-Oriented and Pricedural/Imperative styles; each has a place in Web development. Examples of Functional Programming languages include Scheme, Erlang, and Haskell.

Higher Order Functions

The main focus of this article will be the Functional Programming concept of using higher order functions to improve code modularity. A function becomes a Higher Order function when it treats other functions as values. JavaScript is very well suited for this type of programming because functions are actually a Function object type. Observe the following two functions:

function sum(x,y,z) { return (x+y+z); }

var sum = function (x,y,z) { return (x+y+z); }
alert(sum(1,2,3)); //6

Although the two functions above may look equivalent, the ability to define a function as a variable has some far-reaching implications:

  • You can pass functions to other functions
  • Functions can return another function
  • Functions have scope, just like any other variable

Take a look at the following code and see how functions can be utilized in Higher Order programming:

function testFor(fn) {
return function() {
for (var i = 0; i < arguments.length; ++i) {
if (fn(arguments[i])) return true;
}
};
}

function even(n) { return !(n % 2); }

var testForEvenNumbers = testFor(even);
alert(testForEvenNumbers(3, 5, 7, 2)); //returns true

In the above example, the testFor() function accepts another function as an argument and applies it to each of the passed function's arguments until it returns true. Should none of the function calls return true, the function exits without returning anything. The will be evaluated as 'undefined' by any subsequent tests and interpreted as false. Another trait of higher order functions is the returning of another function. This is exactly what happens here, as the testFor() function does not return the results of the passed function, but rather, an anonymous function containing the passed function. The returned function is stored in the testForEvenNumbers variable and subsequently called just like any other function.

We can further incorporate functional programming into our testFor() function by using some of the new JavaScript 1.6 map() and indexOf() Array methods. The map() method takes a function as a parameter and applies it to each element in an array. The indexOf() function searches through an array and returns the index of the first instance that contains the object that we are looking for. A search that fails to turn up the object in question returns an index of -1. It accepts the object that we are looking for, as well as an optional element index to start at. The only problem is that the function's arguments property is not an array. Before calling map() and indexOf(), we need to convert the arguments into a proper Array object. This is done by applying the Array's prototype slice() method on it. From there we can chain the functions together by mapping the passed function (fn) to all the elements in the arguments array and then calling the indexOf() against the returned values, searching for the true boolean value:

function testFor(fn) {
return function() {
return Array.prototype.slice.apply(arguments).map(fn).indexOf(true) > -1;
};
}

This is a very powerful way of writing code because it leverages higher order functions that are well documented and tested, thus requiring less writing and testing on our part.

Function Scope Primer

Used properly, function scope, like any variable, can enhance security and protect variables from being changed unintentionally. Conversely, misunderstanding the rules of scoping in JavaScript, and you could have some really cryptic and evasive bugs on your hands! Any function defined at the level is global, and is accessible to every function, object, and sub-function, regardless of their location in the code. Functions that are defined inside another function are trickier because the scope depends on how we define the inner function. At the top of the article we saw that there are two ways of defining a function: var fn = function() {} vs. function fn() {}. There are a couple more options that we haven't seen yet. The last one, which is by using the Function() constructor, doesn't affect scoping, so we'll leave that for later. It is the fn = function() {} syntax that can cause trouble. Whereas both the methods described earlier will create private variables when defined within another function, dropping the var keyword will always result in a global function being created, no matter where it is defined. The cause of this quirky behavior is that the var keyword is optional. Omitting it will cause the scripting engine to create the variable automatically if there isn't one by that name already and add it to the global window object. Ergo: the var identifier is important! The following code snippet demonstrates the finer points of function scoping:

var globalFunction = function () // global, can be accessed anywhere.
{
//some code...
}

var containerFunction = function() // global, can be accessed anywhere.
{
subFunction = function()// global to everything (no var keyword for new variable)
{
globalFunction(); // We can access global Function here 2 levels deep.
var privateFunction = function() {}; //private to subFunction().
}
globalFunction(); // We can access global Function here 1 level deep.
subFunction(); // We can access subFunction inside containerFunction.
privateFunction(); // will cause an error.
}

containerFunction();
subFunction(); // This executes because we defined subFunction WITHOUT
// the var keyword so it was created with a global scope.
privateFunction(); // still doesn't execute.

What is Lambda?

The concept of using a function as an argument to a function call is called lambda. Lambda derives from lambda calculus and is a formal system designed to investigate function definition, function application and recursion. Developed in the 1930s, lambda has emerged as a useful tool in the investigation of problems in computability or recursion theory, and forms the basis for functional programming. Functional programs are stateless and deal exclusively with functions that accept and return data (including other functions), but they produce no side effects in 'state' and thus make no alterations to incoming data.

The Function Object

It is important to keep in mind that a function in JavaScript is not just a variable type, but a full-fledged object. In fact, all native JavaScript data types have an equivalent object, which stores its properties and methods. For instance, when we create a string using the following syntax: var aString = "This is a string.", a String object is automatically created behind the scenes. This is what allows us to check its length using aString.length or call a method such as aString.split(', '); on it. In addition to having properties and methods, each object has at least one constructor. In the case of a String, we could also create one in the following manner: myString = new String("This is a string object").

The Function object also has a constructor: new Function(string arguments, string body). Here is how we would create the testFor() function via the constructor:

var testFor = new Function("fn", "return function() { return Array.prototype.slice.apply(arguments).map(fn).indexOf(true) > -1; };");

The arguments parameter must consist of a comma-delimited list of valid JavaScript identifiers. In this case there's only one argument called "fn". The body is also a string containing all of the function code caontained within the function block's opening and closing curly braces {}.

Generally using the Function's constructor to define functions should be kept to a minimum because it is generally slower than using one of the means that we discussed previously. However there are times where it may be appropriate to create one on the fly. We'll be looking at just such a situation in the "Self Invoking Function" section.

Function Properties

arguments: An array of all the arguments passed to a function.

arguments.callee: Returns a reference to the current function. Can only be used within the body of a function.
arguments.length: Returns the number of arguments passed to a function.

constructor: Specifies the function that creates an object's prototype. It is a direct reference to the function itself.

length: Specifies the number of arguments expected by a function. It is external to the function and is not the same as the arguments.length property, which specifies the number of arguments actually passed to a function.

prototype: A value from which all instances of an object are constructed, and which also allows you to add other properties and methods to an object.Function Methods

apply: Allows you to more easily pass function arguments and this pointer to another function.

call: Allows you to call a method within a different context.

toSource/toString/valueOf: All three methods return a string representing the source code of the function. They override their respective Object methods.

The following code uses the arguments.length and Function.length properties to compare the number of expected arguments to the number actually received. An error is thrown if they don't match:

var myFunc = function(arg1, arg2, arg3)
{
if (arguments.length != myFunc.length)
{
throw new Error("myFunc expected " + myFunc.length + " arguments and only received " + arguments.length + ".");
}

//continue processing
}

myFunc(99);

Anonymous Functions

Back in our original testFor() function, we defined our function and returned it at the same time: return function() {};. There was no need to name it because it was going to be assigned to a variable straightway. A function created without a name is called an anonymous function. In modern rich client applications, this functional programming tenet has become very much in vogue, despite its lack of adherence to OO practices. They are most commonly used in Ajax routines and event handlers because both the HttpXmlRequest and Event objects accept functions to be assigned as handlers. The HttpXmlRequest's onreadystatechange property, as well as the onmousedown, onkeypress, onblur, and onload are all examples of handlers that require a function to execute. A handler function should always be anonymous because once it has been assigned, there is no need to call it again. Instead, the event should be fired, using code like the following:

var resultsTable = document.getElementById('results_table');

resultsTable.onmouseover = function() { this.style.bgcolor = 'blue'; };
resultsTable.onmouseout = function() { this.style.bgcolor = 'white'; };

//to fire
resultsTable.onclick = function() { this.fireEvent('onmouseout'); };

The Self-Invoking Function!

Self-invocation (also known as auto-invocation) is when a function executes immediately upon its definition. This is a core pattern in programming and plays a key role in many other JavaScript patterns. I like to think of it as a shorthand factory definition for generating a function based on a set of criteria. To elaborate on our previous example, we could use self-invocation to create a cross-browser version of the fireOnChangeEvent() function. This time we would return one of two functions, depending on what browser style is being used. A ternary ( expression ? true : false ) operator tests for the fireEvent() method on the this pointer. The self invocation is written as an extra set of parentheses after the function definition. It is also considered to be good practice to include another set of parentheses around the function as well. The following example uses the Function.call() method to execute the self-invoking function within the scope of a element called baseList:

var fireOnChangeEvent = (function()
{
var BUBBLES = true, CANCELABLE = true;

return ( this.fireEvent //IE
? function() { this.fireEvent("onchange"); }
: function() //Mozilla
{
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", BUBBLES, CANCELABLE);

this.dispatchEvent(evt);
}
);
}).call(document.getElementById('baseList'));

//to fire the onchange event
fireOnChangeEvent.call(list);

Here's another self-invoking function that creates a getter() method using the name that is passed to it. The value that we generating the getter() for can be of any type because the JavaScript engine will automatically promote native data types to their respective Objects. The inner anonymous function is defined using the Function constructor so that the getterName can be set. Passing the function body to the constructor as a string has the advantage of executing the code much like the eval() function does. We self invoke the anonymous inner function so that the value gets set once at creation time. Now, whenever the getter is called, it will return the value of the this pointer when the public outer generateGetter() method was called:

Object.prototype.generateGetter = function( name )
{
var value = this;
var getterName = "get"
+ name.charAt(0).toUpperCase()
+ name.substring(1);

return (new Function( "value", "return function " + getterName + "() { return value; }"))(value);

}

var obj = {};
var getter = 'a string'.generateGetter('test');
obj[getter.name] = getter;
alert(obj.getTest()); // 'a string'

getter = (true).generateGetter('test2');
obj[getter.name] = getter;
alert(booleanTest.getTest2()); // true

Recursive Anonymous Functions

A recursive function is one that calls itself until a certain condition exists - sort of like a loop but using an if statement instead. A problem arises when you try to use anonymous functions recursively because it's difficult to call a function with no name! That's what the arguments.callee property was created for. The following curryToResult() function is extended from the tradition curry() function. Function currying is the preapplying of function parameters and then filling the rest at a later time, over one or more execution calls. You can read ore about function currying in my article entitled "The Partial Function Application". The curryToResult() function below takes it a step further and returns the results of the function once all of the parameters have been supplied. We can see in the inner anonymous function that the curry() method is called as long as the argument.length is less than the numberOfExpectedArguments. The curry function is applied to the current function using the arguments.callee property until the condition evaluates to true:

Function.prototype.curryToResult = function(numberOfExpectedArguments)
{
numberOfExpectedArguments = numberOfExpectedArguments || this.length;
var method = this;

return function()
{
return arguments.length >= numberOfExpectedArguments
? method.apply(this, arguments)
: method.curry.apply(arguments.callee, arguments);
};
};

We are just starting to see the extent to which JavaScript can be utilized with Functional Programming methodologies to create some very efficient and stable code. Moreover, by using functions as arguments, you can create reusable code modules that you can plug directly into your functions and have them processed in predictable and generic ways. We are already seeing examples of this in many JavaScript Frameworks, such as Prototype, and Mootools, which allow you to add to classes by passing other code modules to it. A great example is a sorting algorithm that accepts a comparison function with which to compare objects. I'm sure that you will also find some of your own applications for functional programming.

Published by Rob Gravelle

Rob Gravelle resides in Ottawa, Canada, and is the founder of GravelleConsulting.com. Rob has built systems for Intelligence-related organizations such as Canada Border Services, CSIS as well as for numerous...  View profile

To comment, please sign in to your Yahoo! account, or sign up for a new account.