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

Functional JavaScript: Harnessing the power of the Function Object

By Rob Gravelle


[next]

Harnessing the power of the Function Object

The JavaScript language can operate equally well within many of the major programming paradigms. The first programming model most students learn is Procedural Programming; so called because procedures (functions) are used to group similar functionality. JavaScript also supports most of the features of the Object-Oriented (OO) model, 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 closer to true OO style. In this article, we explore the Function object and learn about its role in a lesser known style of coding called Functional Programming. Our specific area of focus is the Functional Programming concept of using Higher Order functions to improve code modularity. Ironically, JavaScript might be the most widely deployed Functional Programming language in use today, but most people are 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

Functional Programming 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, the most likely cause of accidental variable modifications are functions that have access to global objects. The reason 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 isn't 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

A function becomes a Higher Order function when it treats other functions as values. JavaScript is well suited for this type of programming because functions are actually a Function object type. Observe the following two functions:

While the two functions above may appear the same, 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.

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

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. If none of the function calls return true, the function exits without returning anything. This 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, since the testFor() function doesn't return the results of the passed function, but another function which contains the passed function. The returned function is stored in the testForEvenNumbers variable and subsequently called 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 element that contains the object we're looking for. A search that fails to turn up the object in question returns an index of -1. It accepts the object we're seeking, as well as an optional element index. The only problem is the function's arguments property isn't 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. 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 indexOf() against the returned values, searching for the true boolean value:

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


[next]