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
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