Functional JavaScript: Harnessing the power of the Function Object | 3 | WebReference

Functional JavaScript: Harnessing the power of the Function Object | 3


[prev]

Functional JavaScript: Harnessing the power of the Function Object [con't]

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 straightaway. A function created without a name is called an anonymous function. You will often see anonymous functions used as event handlers and Ajax callbacks as both the HttpXmlRequest and Event objects accept functions to be assigned to certain properties. The HttpXmlRequest's onreadystatechange property, the onmousedown, onkeypress, onblur and onload are all examples of handlers requiring a function to execute. A handler function should always be anonymous because once it has been assigned, there's no need to call it again. Instead, the event should be fired, using code like the following:

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's 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 <SELECT> element called baseList:

Here's another self-invoking function that creates a getter() method using the name passed to it. The value we're generating the getter() for can be of any type because the JavaScript interpreter will automatically promote native data types to their respective Objects. The inner anonymous function is defined using the Function constructor so 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. We self-invoke the anonymous inner function so the value gets set once at creation time. After that, whenever the getter is called, it returns the value of the this pointer when the public outer generateGetter() method is called:

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 why the arguments.callee property was created. The following curryToResult() function is extended from the tradition curry() function. Function currying is the pre-applying 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:

We're just starting to see the extent to which JavaScript can be utilized with Functional Programming methodologies to create code which is both more efficient and stable. Moreover, by using functions as variables, you can create reusable code modules that you can plug directly into your functions and have them processed in predictable and generic ways. We're 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. You could create several to compare different classes without changing the original comparison function. I'm sure you'll also find many to improve your own code using Functional Programming.

Original: January 12, 2009


[prev]