First class functions in JavaScript

This article was originally published in VSJ, which is now part of Developer Fusion.

Last month we looked at the admittedly confusing world of JavaScript objects in their raw and untamed form. Many experienced JavaScript programmers would have failed to recognise this as the usual approach to the whole problem, and this is because in JavaScript the function occupies a rather unique role – it’s a first class object. This much is fairly well known, but it’s also a first class object that differs from more basic objects. This month we take a look at some interesting ways that functions and objects work together.

Function basics

There are at least three distinct ways of creating a function, and this does nothing to make understanding easy.

The first way is to use the function statement. This is the most common way of creating a function, and the one that beginners are generally taught:

function myfunc1(a)
{ return a + 1; };

In this case myfunc1 is a “function name” and not a simple variable.

The second is to use the function operator:

var myfunc2 = function(a)
{ return a + 1; };

This form is often used to construct anonymous functions and often encountered as part of object-oriented JavaScript.

The third way is to use the Function constructor. As explained last month every object has a constructor and Function constructs a function object:

var myfunc3 = new Function(
    “a”, “ return a + 1;”);

That is, the Function constructor accepts a variable number of string parameters – the last of which is the function body and the remainder are functions. Also notice that Function is always treated as if it had been written as new Function, i.e. it always creates a new object.

All three ways create a function that you can call in the same way, e.g. myfunc1(34) etc. From this point of view they are identical. However, the first creates a function variable and the second just a standard variable that references a function. You can use the second form to create a function variable as well if you want to:

var myfunc2 = function myfunc4(a)
{ return a + 1; };

Now you can call the same function using myfunc2 or myfunc4. You can think of the function operator as being used in both cases such that it defines a function variable if one is provided and a standard reference variable if one is used.

The big difference is between the first two and the third. This creates a function object on the fly in the sense that its parameters are strings that might well be constructed at run time rather than compile time. The function operator/statement can’t be used in this way and so it is possible for the JavaScript engine to perform optimisation at “compile” time (although you need to keep in mind that JavaScript is an interpreted language). In this sense the Function constructor is a lot like the Eval function which will evaluate any JavaScript commands stored in a string. If you are worried about efficiency don’t use the Function constructor.

Arguments

The rule for function arguments is that they are always passed by value. However, some variables are value types, like simple numbers, and some are reference types, like objects, and this gives the appearance of pass-by-value and reference semantics. What this means is that if you pass a numeric or string value then within the function the parameter is a copy of the value. Then any changes made to the parameter in the function don’t change the variable in the rest of the program. However, if you pass an object then the parameter is again a copy of the value, but in this case it’s a reference to an object and this is the same object referenced in the rest of the program. Hence any changes you make to the parameter don’t affect anything in the rest of the program, but any changes you make to the object that the parameter references do make permanent changes. This is exactly how it is in languages such as C# and VB, so it’s worth getting it absolutely clear. For example if we define:

function myfunc1(a)
{   a = 2; }

Then after:

var b = 1;
myfunc1(b);
alert(b);

…b is still 1 despite the function’s “attempt” to change it to 2. However, if the function is redefined to be:

function myfunc1(a)
{ a.x = 2; }

…that is we are changing the x property of an object, then following:

var b = { x: 1, y: 2 };
myfunc1(b);
alert(b.x);

…the x property of b, which was initialised to 1, is changed to 2. However, if we change the parameter (not a property of the object it references) then again the function has no effect on the rest of the program:

function myfunc1(a)
{ a = { x: 2, y: 2 }; }

With this definition of the function b.x is unchanged when the function returns. To be clear, if the function a initially references the same object as b, then it is set to reference a new object and finally it is destroyed when the function ends leaving b referencing the original object.

So JavaScript always passes by value but the effect changes according to the type of variable passed.

There seems to be no way to pass a primitive value such as a number by reference. You can try wrapping it as an object as in:

var b =new Number(2);

…but the value of the new Number object, i.e. 2, is an internal property that you can’t access and this stops you using primitive types as if they were objects in creative ways.

The closest approach to passing a primitive value by reference is to create a new object type with a new value property that is accessible. This isn’t particularly practical but it is a good example of object-oriented JavaScript in action. First we need the new object type and so we need a constructor function:

refNumber = function(value)
{
    var o = new Number(value);
    o.value = value;
    return o;
}

The first line creates a new Number object with its internal value set to the specified value. We then add a value property which is also used to store the value. Notice that we explicitly return a reference to the new object that has been created. With the new constructor we can now create new refNumber objects:

var b = new refNumber(1);

At this point b behaves like a standard number, set to 1, within expressions but notice that if you assign a new value to it then it simply reverts to being a standard Number object. If a function wants to change the value of this refNumber object then it has to explicitly change its value property:

function myfunc1(a)
{ a.value = 2; }

If you now call the function using b

myfunc1(b);
alert(b.value);

…then the value of b will have been changed to 2. Of course the internal value will not have been changed and if you use b in an expression it will still be set to 1. The only solution is to “normalise” the internal value to be the same as the value property but this can only be done by creating a new refNumber object:

var b = new refNumber(1);
myfunc1(b);
b = new refNumber(b.value) ;
alert(b);

Now you will discover that the internal value of b is also set to 2. This isn’t entirely satisfactory as you have to remember to use the value property within the function and you have to remember to normalise the variable after its use. Even so it’s impressive that you can get this close to automatic pass by reference using nothing but the JavaScript language.

Bring in the clone

What about other side of the coin, passing a copy of an object? This turns out to be fairly easy – all we need is a clone function. For example, consider the following code:

function myfunc(o)
{ o.x=2; }
var a = { x: 1, y: 2 };
myfunc(a);
alert(a.x);

The function changes the x field in the a object and the alert prints 2 not 1. A clone function simply creates an object with all of the properties of an existing object. The simplest clone function is:

function clone(o)
{
    var c=new Object();
    for(p in o)
    { 	c[p]=o[p]; }
    return c;
}

The for(p in o) iterates through all of the properties of o and the line c[p]=o[p] creates a new p property in c and assigns the property o[p] to it. Note the use of the selector [p] notation rather than the equivalent dot notation simply because p is a variable. With the help of the clone function we can now pass a by value/copy:

myfunc(clone(a));
alert(a.x);

Now the value of a.x is unchanged by the function. Of course there is a flaw in this version of clone in that it only works as long as the properties of the object aren’t themselves objects. If they are, our current clone simply copies the references to them and doesn’t clone them in turn. This is often called a shallow copy.

To make a deep copy you need to call clone on each object property:

function clone(o)
{
    var c=new Object();
    for (p in o)
    {
    	if (typeof (o[p]== “object”))
    	{ c[p]=new clone(o[p]); }
    	else
    	{ c[p]=o[p]; }
    }
    return c;
}

This function returns a deep copy of any object and in this respect is a useful general purpose function. It can be used, for example, to stamp out new copies of an object as an alternative to using new and the rest of the object-oriented machinery. To see the deep copy in action we need a slightly modified test example which uses an object with an object property:

function myfunc(o)
{ o.x.v=2; }
var b = { v: 1, w: 2 };
var a = { x: b, y: 2 };
myfunc(a);
alert(a.x.v);

Notice that now a is an object with a property x which is itself an object, i.e. b. The function now changes the v property within b and if you run this you will see that v is changed to 2. If you change the function call to:

myfunc(clone(a));

…then the function gets a deep copy of the a object to work with and it doesn’t change v which is displayed as 1.

Function scope

A final thought about functions is that it is very important that you realise and remember that JavaScript, unlike most other languages, does not use block scope but function scope. That is, a local variable is local to the function it is declared in and it is created and destroyed along with the function. For example:

function myfunc1()
{
    var a = 1;
    { var a = 2; }
    alert(a);
}
myfunc1();

If JavaScript supported block scope then the second variable a would be different from the first and would override the first for the duration of the block – i.e. until the end of the closing curly bracket. However with function scope it doesn’t and both a’s are the same variable. In this case it’s obvious but when variables are declared within loops and if statement it is all too easy to suppose that they are unique when they aren’t. On the other hand any variables that you do declare within a loop or if block are available for use within the rest of the function. For example:

function myfunc1()
{
    if (1 == 1)
    { var a = 1 }
    alert(a);
}
myfunc1();

…works fine and displays the value 1.

You might also like...

Comments

About the author

Ian Elliot United Kingdom

Ian Elliot is a development programmer with I/O Workshops Ltd, a consultancy which solves real-world problems for clients with widely varying requirements.

Interested in writing for us? Find out more.

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“An idiot with a computer is a faster, better idiot” - Rich Julius