Functional Javascript

By Patrick Hunlock Lisp? Scheme? Erlang, Haskell? Forget about them! The most widely deployed functional programming language is Javascript. Borrowing a trick or two from the transformers, Javascript masquerades as a procedural language until you're ready to take it to the next level.

Procedural Functions
In the beginning there was the function…
function hello(who) { alert('Hello '+who); } hello('world'); // outputs "Hello world"

Nearly every programming language has a construct similar to this. Every programmer in the world is comfortable with this syntax. hello is the name of our function, but what happens if we make hello the same as a variable name?

Functions As Variables
It may be a little unfamiliar in syntax but most programmers should be comfortable with a function that's defined like a variable.
var hello = function (who) { alert('Hello '+who); // outputs "Hello world" } hello('world');

There's no big difference here, just add a var tag, an equal sign and shift where hello appears, everything else is the same. We call it the same way, it does the same stuff. Take a look at that definition again. This is more than just visual sugar -- a pretty way to define a function. This construct actually means something. It means that our function is going to follow the same rules and abilities as any other variable in Javascript. It will have the same scope and it can be passed to other functions just like any other variable.

ab
Functional Javascript Page 1 of 10

or you can execute the function in the call and pass the return value of the function. So in Javascript a function can be passed just like an array or an object or any other variable.but that's OK. // return a pointer to the pushedMyButton function } document. Now when the onclick event is set up. The example above passed a pointer of the hello function to the variable what in the say function. or as the result of a function returning one to it ( onclick=doSomething() ). Because we only used the function name and not doSomething(). If doSomething() passes back a pointer to another function then the event will actually still work.we're not passing anything -. onclick now has a pointer to doSomething. it can take it either directly ( onclick=doSomething. For instance… function doSomething() { alert('you pushed my button!'). what then became a pointer to hello.Passing Functions To Functions If we declare hello like a variable. } function doSomething() { return pushedMyButton. // outputs "Hello say function" } say(hello). There are two ways to use a function as an argument. In this example. You can pass a pointer to the function itself. On the otherhand. if we were to use doSomething() things will still work out OK as long as doSomething() returns a pointer to a function… function pushedMyButton() { alert('you pushed my button!'). which is the only thing onclick wants. This example gives the function doSomething to the onclick event. } var hello = function (who) { alert('Hello '+who).onclick=doSomething. The parenthesis are an empty set -. Or put another way. they tell Javascript that we want to execute the function not pass a pointer to it. doSomething returns a pointer to a function. doSomething is executed because we appended parenthesis at the end. var say = function(what) { what('say function'). } document. Functional Javascript Page 2 of 10 . anything that can hold a value in Javascript can hold a function. it kind of makes sense that we can pass it like one as well.onclick=doSomething(). If you've ever made an event in Javascript you've probably already used the pass as pointer concept because all the event handlers want a pointer to a function to call when they're tripped. onclick doesn't care how it gets the pointer. ) .

As an aside. // testCopy is a pointer to the test function() var testStr = test(). Which leads us to another concept of functional programming. the handler calls the anonymous function which simply throws up an alert box.Just to recap. Lambda is represented by the λ character. var test = function () { return "This is a String". Lambda. } var testCopy = test. This function is anonymous because we didn't declare a name for the function. Javascript will execute the function and pass along the return value of the function. Keep that difference in mind. even if they're just an empty set -. It is the 11th letter of the Greek alphabet. Anonymous Functions Chances are. } This sets up an event handler whenever the mouse is pressed. You'll also see argument variable names named lambda used to indicate that variable will be receiving a function. If you follow up a function name with argument parenthesis. we'll be coming back to it a little later. but in every place that matters. When the mouse button is pressed. For instance… document. it's probably pure coincidence that Lambda Lambda Lambda was the fraternity in Revenge of the Nerds. Worse. // testing contains "This is a string" Lambda.(). it gets thrown around like everyone already knows that lambda is using a function in an argument in a call to another function.onmousedown = function() { alert("You pressed the mouse button"). learning to look at the function as a piece of active data will really help you out when it comes to figuring out just how to apply this technology. Functional Javascript Page 3 of 10 . and it's just another value in the machine. we can't call it later unless we somehow go through onmousedown. if you've ever written an Ajax routine or an Event handler in Javascript you are familiar with an anonymous function. It's data that does stuff to be sure. in psuedo-code. Lambda If you've mastered the concept of passing functions as arguments to other functions then congratulations! You now understand lambda which basically just means using a function as an argument in a call to another function. if you don't follow a function name with argument parenthesis then you're passing the function as a pointer. Visually. If a function doesn't have a name. // testStr contains "This is a string" var testing = testCopy(). then functions in Javascript are much closer to data than what we would consider traditional functions and objects. So if you see something like "Here we'll use a lambda expression" it just means they're passing a function as an argument. Lambda is a pretty big buzzword in functional programming and it gets thrown around a lot.

document.src="http://mydomain. It accepts animal1 and animal2 as arguments and it gets those values from the trailing parenthesis which pass ' cat' and 'dog' respectively. That's it.body.com/script. First Bookmarklete App</A> s=document.appendChild(s). In this example we have a traditional doAlert(msg) function. A more common real-world example of this is the following bookmarklete code which attaches an external Javascript to the current page. creates a new script tag.})(). self-invoking function as its msg argument. document. 'dog') ). } ) (). // Outputs: 11. Observe… function doAlert(msg) { alert(msg). And when we ask for the value of x we get 11 instead of the function. The function existed only long enough to generate 11 and give it to x then it's gone. And of course 'cat' and 'dog' could be variables.appendChild(s). When we ask for the typeof of x we get "Number" as the result -. msg will be the returned value of the anonymous function. When Javascript comes across this line it will execute the function and put the return value in x. then appends it to the document. when executed. Because it's a selfinvoking function it works great in a link which can be dragged into the bookmark or link bars to make a bookmarklette… <A HREF='javascript:(function(){var s. this example uses two arguments in the self-invoking function. What we did here was wrap a function in parenthesis and then add in the argument parenthesis. “x” isn't a function because we invoked the anonymous function inside the parenthesis with a set of argument parenthesis.createElement("script"). } doAlert( (function(animal1.writeln(typeof(x)+'<BR>').createElement("script"). but it's invoked with an anonymous.writeln(x).not a function. self-invoking function and it's really quite powerful. s.Self-Invoking Functions Consider for a moment the following code… var x = (function () {return(5+6)})().body.js". although it's hard to see that power in the little example. To further illustrate how anonymous and self-invoking functions work.com/script. document. This is an anonymous.'>My You can also use lambda self-invoking functions (buzzword heaven!) as a sort of shortcut when you need to do some light processing of data before you pass it on to another function. Something like this… Functional Javascript Page 4 of 10 .animal2) { return animal1 + ' loves ' + animal2. This code.js". // Outputs: Number document. and doAlert could be in a loop zipping through an array of data. ( function () { var s=document. } ) ('cat'.body which will automatically load the external Javascript file.src="http://mydomain. sets its external source.

num2) { return num1 + ' + ' + num2 + ' = ' + (num1+num2). } for (i=0. i<10. I pulled this term from one of Dustin Diaz's articles. i+5) ). self-invoking functions as well! Here's a modification of the example above where the anonymous function has been changed to be a regular function named buildString. i<10. i+5) ). The trailing parenthesis pass the arguments to the anonymous-function. and these values will be used to set up the string. self-invoking functions. There's no official naming convention for what we're calling anonymous. but as you might have suspected you can also do named. } And of course this is just a variation on the more traditional function call… function doDisplay(msg) { document. For ten times. Well that pretty much covers anonymous.writeln(msg+'<br>'). } for (i=0. i+5) ). “Immediate” is shorter. } ) (i. self-invoking functions. i<10. } function buildString(num1.function doDisplay(msg) { document. } function buildString(num1. it will call doDisplay and its self-invoking function will set up a string to pass to doDisplay.num2) { return num1 + ' + ' + num2 + ' = ' + (num1+num2). num2) { return num1 + ' + ' + num2 + ' = ' + (num1+num2). i++) { doDisplay( (buildString) (i. i++) { doDisplay( (function(num1. } Here we actually have a loop set up. self-invoking is a bit more descriptive.writeln(msg+'<br>'). ab Functional Javascript Page 5 of 10 . function doDisplay(msg) { document.writeln(msg+'<br>'). Douglas Crockford calls these functions: immediate anonymous functions. } for (i=0. i++) { doDisplay( buildString(i. } Which will work equally well.

} var copiedFunction = originalFunction. can be accessed anywhere. and sub-function regardless of their location in the code. Internally. } containerFunction(). var subFunction = function() { // private--global to containerFunction and its children only. subFunction() // We can access subFunction inside containerFunction. the copiedFunction retains its pointer to the original function (hello world) while originalFunction is now pointing to a new function block in the heap (goodbye world). alert('hello world'). can be a little quirky. “copiedFunction” is a pointer to the hello world function that was initially defined.variables defined inside a function are private to that function and its sub-functions or children. alert("I'm Private").with one caveat -. Functional Javascript Page 6 of 10 . // outputs Hello World. globalFunction(). Understanding Function Scope Because Javascript functions are treated like ordinary variables. that function occupies a block of memory. subFunction(). object. accessible to every function. // We can access global Function here 2 levels deep. Functions defined at the <script> level are global. the only reference it has is its location in Javascript's heap. } globalFunction().Understanding Function Pointers When you create a function. // This produces an error because // subfunction() only exists inside containerFunction The caveat? The caveat is if you declare a new variable without the var keyword inside a function it becomes global in scope. When you pass a pointer to the function you're passing the pointer to this memory location and NOT the function's name. var originalFunction = function () { alert('goodbye world'). can be accessed anywhere. var globalFunction = function () { // global. in Javascript. This is best illustrated in code… var originalFunction = function () { alert('hello world').which. // We can access global Function here 1 level deep. } copiedFunction(). When we later change the original function to say goodbye world. } var containerFunction = function() { // global. It's a quirk of the language that catches many people unawares. Variables in Javascript have function scope not block scope which means that -. they have the same scope and rules as ordinary variables -. array.

var myArray = []. the properties ('one'. } containerFunction(). can be accessed anywhere. subFunction(). myArray[1] = 1. in Javascript.two = 'two'. 'three') aren't a part of the real array they're properties of its object. . This is mostly transparent until you deliberately set out to create object-oriented code. as needed.one = 'one'. myArray[2] = 2. It does what you define it to do. We used the . // This executes because we defined subFunction WITHOUT // the var keyword so it was created with a global scope. subFunction() // We can access subFunction inside containerFunction. Functions As Objects All functions in Javascript are objects. myArray[2] = 2. subFunction = function() { // global to everything (no var keyword for new variable) alert("I'm Private"). in Javascript.length property to find out how many items were in the array.sort. } var containerFunction = function() { // global. Functional Javascript Page 7 of 10 . myArray. At the top we have the Array itself and below that is the object for that Array which we can also use to store data in its properties and create any methods we want in addition to drawing on common methods and properties all Arrays share (like . // We can access global Function here 1 level deep. 'two'. globalFunction(). Underneath myArray is its object. myArray. are like Arrays in that at the top level you have the function itself. } globalFunction().writeln(myArray[i]). is also an object. At its top level an Array is an Array… var myArray = []. When we loop through myArray we're only going to get back [1][2][3] (1.3). for (i=0. can be accessed anywhere.length. which has properties and methods common to all Arrays and which you can extend upon. An Array.three='three'. But check out the loop statement.concat. i<myArray. i++) { document. exists on two levels. . // We can access global Function here 2 levels deep.length. in Javascript. myArray. But underneath that is the function's object and that object has common properties and methods and those properties and methods can be extended on by you. alert('hello world'). myArray[3] = 3. } Here we load up both the array and the properties of the Array object. myArray[3] = 3. myArray[1] = 1.var globalFunction = function () { // global.2. etc). So the Array. Functions.

Stores the number of arguments in the array arguments. var myFunc = function(a.2). As you can see. Every function has the following methods… • • • • • Understanding Function Arguments The argument list in your function declaration can be considered a recommendation. } myFunc(1). b = b || 2.Allows you to call a function within a different context. call -.5.} document.length property and the arguments.6.length property allow you to check for the expected number of arguments and the number of arguments actually passed. The safest way to correct for an unsent argument is to look for undefined as this prevents values such as false and null from appearing as an unset variable. length -. toSource -.4.3.b.8.callee -.writeln(a+'<br>'+b+'<br>'+c+'<BR>').An Array/object containing the arguments passed to the function • arguments.2. prototype -. toString -.A method that lets you more easilly pass function arguments.c) { if (!a) {a=1}.9.b.Pointer to the executing function (allows anonymous functions to recurse). The function .function pointer to the constructor function. If myFunc(1) is called then b and c will be of type undefined and you can look for this in several ways. apply -.Returns the source of the function as a string.Returns the source of the function as a string.2.length -.10).Returns the source of the function as a string.y) = 2. if (c==undefined) {c=3. constructor -. myFunc(1. If you have the following… var myFunc = function(a.The number of arguments the function was expecting myFunc(x.7.allows the creation of prototyes. undefined is a false condition so you can use boolean operators to detect if an argument wasn't set and correct it.3).c) { } You can still call the function the following ways… myFunc(1). myFunc(1. valueOf -. myFunc(1. For instance… Functional Javascript Page 8 of 10 .Function Objects and Methods Every function has the following properties… • • • • • arguments -.

Howto Pass Arguments To Another Function Every now and again.4.b. After this article was published Matthew Eernisse (Author of Build Your Own Ajax Web Applications) noted that the arguments property isn't the same as user-defined arrays.6. Earnisse provided a very elegant solution. var args = Array. for(i=0.prototype.7. var myFunc = function() { document. // Outputs: 10 otherFunc(arguments).8.3.9. i++) { document.7.').length).2.length). While you access the elements the same and .9.5.2.6. // Outputs: 1 -. Here we pass 10 arguments to myFunc and myFunc tries to pass them to otherFunc but instead we pass it the arguments array and not an arguments list.writeln(arguments.9.length is the same.3. i<arguments. someone asks how to pass the arguments to another function as arguments instead of an array. For instance… var otherFunc=function() { alert(arguments.5.writeln('got ' + arguments.7.2.writeln('expected '+myFunc.10).5.length+'<BR>'). Mr. if there were too many.length+' arguments. and c represented variables we used to capture the first three arguments. } } myFunc(1.4. //Outputs: 3 document.an array } var myFunc = function() { alert(arguments. splice.b. the function expected 3 arguments but got only 1! Mastering the Arguments Array In our example above a. We can work around this with a function method called apply which will apply the arguments array as an arguments list in the new function. As you can see. If you'd like to be able to manipulate the arguments array with the same tools you use to manipulate a normal array.apply(arguments).length.3. etc) that a user-defined array contains.8. //Outputs: 1 } myFunc(1).4.6. slice. // displays 10 // displays: 1.length+ ' arguments. With this code args becomes a proper array copy of arguments.<BR>').8.10. well they would still be available to us in the arguments array. If there weren't enough arguments the variables were set to undefined. the arguments array doesn't have all the methods (sort. } myFunc(1.slice.writeln(arguments[i]+'.10).<BR>').c) { document.var myFunc = function(a. Functional Javascript Page 9 of 10 .

}else{return n*arguments.7 License Copyright © 2007 by Patrick Hunlock – http://www. call itself.3.03.length).0. if(n <= 1){return 1. } myFunc(1. but that is subject matter for another.6. Permission is granted to keep a copy for your own use.9.var otherFunc = function() { alert(arguments.hunlock. ab Version This document is current as of Firefox 2. future. however.callee property contains a pointer to the currently executing function which means an anonymous function can. Javascript 1. How do we call a function without a name? Well in Javascript the arguments. article. For now.}})(10)). Howto use recursion on Anonymous Functions Lets say we have an anonymous factorial function and we want to do it recursively.length).4. arguments). alert((function(n){ 1).5.10).8.com.2. I hope this article has helped you grasp the power and flexibility Javascript functions afford you in expressing your programming goals. but all distribution rights are reserved by the author. // Outputs: 10 otherFunc.6.callee(n- Conclusion There's a lot more to functions in regards to object oriented programming and the Javascript Function object. JSCRIPT 5. // Outputs: 10 } var myFunc = function() { alert(arguments.apply(this. IE 7. The source code (but not the article itself) in this document are released into the public domain and may be used without compensation or attribution. indeed. Functional Javascript Page 10 of 10 . ECMA-262 Edition 3.7.

Sign up to vote on this title
UsefulNot useful