wp-content/uploads/2016/01/PBS_Logo.png

In the previous instalment we introduced the concept of JavaScript functions. We learned how to all existing functions, and how to create out own.

In this instalment we’re going to take our understanding of functions to the next level. The techniques we encounter today would be considered advanced techniques in most other languages, and you could spend years developing in Java and never encounter an anonymous function. However, because of how JavaScript is integrated into HTML documents, these techniques are considered fundamental in JavaScript, and anonymous functions are a dime a dozen!

Before we delve into anonymous functions, we’ll start by taking a deeper look at how JavaScript deals with function arguments.

Our Playground

For this instalment we will yet again be using our JavaScript playground. You can download the code for the playground here, or, you can use the online version at www.bartb.ie/pbsdemos/pbs-JavaScriptPlayground/.

PBS JavaScript Cheat-Sheet

At Allison’s suggestion, I’ve created a JavaScript cheat-sheet which you can use as a quick reminder when working on the challenges. The cheat-sheet reminds you of the core concepts through a series of code samples, and links back to the relevant PBS instalments.

I’ll update the cheat-sheet as we continue to learn more.

Solution to Instalment 15 Challenge

At the end of the previous instalment, I set an optional challenge, and promised to provide a possible solution next time. The challenge was to create a function for calculating the average of an arbitrarily long array of numbers, and use this function to average numbers entered into the inputs in the playground.

There are infinitely many correct solutions to any programming problem, so this is just one possible solution:

Detecting Undefinedness

It should be easy to tell whether or not a given argument was passed to a function, but sadly it’s not.

We know that undefined evaluates to false, so you might think to do something like this:

This does work correctly when no argument is passed, but, it can’t tell the difference between no argument, and any other argument that evaluates to false.

What we need is a proper test for undefinedness. This is where the typeof operator comes in.

If a variable is undefined, then applying the typeof operator to it will result in the string 'undefined'typeof x === 'undefined'. Knowing this, we can re-write our function from above like so:

Getting Clever with Function Arguments

So far, all we know about arguments is that we give them a name in the function definition, and then we access then by that name within the body of the function. Let’s look a little more deeply.

Optional Arguments

It is often the case that the task performed by a function needs some arguments, but others have a sensible default, so it makes sense to have them be optional.

A somewhat contrived simple example would be a function called incrementor(), by default it will increment values by 1, but it can increment by a different amount if desired. In other words, it requires one argument, the number to increment, and optionally supports a second, the amount to increment by. You could implement that function like so:

As you can see, our function behaves in a sensible way regardless of the number of arguments provided.

An Arbitrary Number of Arguments

Optional arguments are very useful, but sometimes you need to write a function that can take any number of arguments – say a function to get the product of any amount of numbers.

A hack you could perform would be to force the caller of the function to pass all the numbers as a single array. This gets messy though – it would be much nicer if you could write a function that would work properly in all these scenarios:

This is where the arguments array comes to your rescue. The argument names we have been using up until this point are completely optional – they are a convenience rather than a requirement. JavaScript actually stores all arguments in a locally scoped array called arguments. We already know how to loop over arrays, so we can use that knowledge to loop over arguments:

In JavaScript, Functions are Objects

We already know that variables can contain literal values or references to objects. We learned that in JavaScript, arrays are objects. In JavaScript, functions are objects too. Because variables can hold references to objects, and because functions are objects, variables can hold references to functions, and, functions can be passed to other functions as arguments.

The function keyword creates function objects. So far, we have been creating and naming our functions in one go using a convenient shortcut notation – let’s strip the shortcut away. When you write this:

You are really doing this:

Each time we have created a function, we have simply been creating a variable with the name we gave our function, and setting the value of that variable to be a reference to the function we created.

We can us this variable just like we can any other variable.

To prove this point, let’s create a function, and copy the reference into another variable name, giving us two references to the same function:

Checking if a Variable Contains a Reference to a Function

To make our code robust, we’ll need to check if a variable does or does not contain a reference to a function. We can do this using the typeof operator. If a variable contains a reference to a function, then applying the typeof operator to it will result in the string 'function', so, we can test if something is a function with code like typeof x === 'function':

Functions as Arguments

To illustrate the power of function references as arguments, let’s create a function to apply an arbitrary function to every element of an array. Our function will take two arguments, a reference to an array, and a reference to a function.

Having to declare and name the functions we want to apply to the array seems wasteful – why don’t we just create the function as we need it, and not name it?

The functions we dynamically created inside the call to arrayApply() were created without giving them a name, this is why they are known as anonymous functions. When a function reference is passed as an argument to another function, it is known as a callback. A JavaScript aficionado may say that arrayApply() function uses callbacks to apply a function to every element in an array.

Iterating Over Arrays with Callbacks

What we have done above is such a common thing to want to do, that there is a built-in JavaScript function for doing it.

Array objects contain a reference to a function called forEach(), which calls a callback with each element of the array as an argument. This is by far the easiest way to loop through an array.

The forEach() function calls the callback with two arguments, first, the value of the element in the array, and second, the position in the array.

Let’s illustrate this with a simple example:

A Challenge

Create a function called inputTransformer(). This function will accept a single argument – a reference to a function object, aka callback. The callback can be assumed to take one argument, and return a value.

inputTransformer() should loop through all the inputs with values entered in the PBS playground, and apply the passed function to each value. inputTransformer() should print the value of each input, and the result of passing that value to the callback.

inputTransformer() should check that it was passed a valid argument, and print an error message if it was not.

Test inputTransformer() by calling it with an anonymous function that squares the inputs, and another that cubes them.

Conclusions

Because of how JavaScript has been integrated into HTML documents, it’s impossible to overstate the importance of anonymous functions and callbacks. If you’ve come to this series with knowledge of more traditional languages like C or Java, you may well be having a harder time of things than those coming to the series with no pre-existing knowledge. This way of working with functions is very different to how you would normally work in in other languages.

At this stage we’ve learned almost all the basic building blocks we need to move out of the playground and into the browser proper – we’ve learned about variables, operators, branching, arrays, loops, and functions. In the process we’ve touched on, but never explained, objects. That’s the next thing we need to do. Then, we’ll look at some built-in objects and functions provided by JavaScript.