Functions

A function contains code, possibly with parameters, that is stored for later use. In both JavaScript and Python, functions are first-class objects. This means that identifiers can have a function as their value, and be used as the parameter or return value of a function.

It’s common, when writing JavaScript for web pages, to create a large number of anonymous (nameless) and similar event-handing functions, one for each node. Often, Delegation (stub) allows us replace a many similar functions by a single function.

Defining a function

When defining a function in JavaScript use

var my_fn = function(arg1, arg2, arg3){
    //  Body of the function.
};

as the template, where of course you get to choose the number and names of the parameters. Unlike Python, you can’t provide default values for the arguments, nor can you provide *args and **kwargs. However, as we will see, there is the pseudo-variable arguments in JavaScript.

This template can be adapted

obj.my_fn = function(arg1, arg2, arg3){
    //  Body of the function.
};

to define an attribute or method of an object. This is most commonly done when obj is a prototype.

You can also put a function in an object literal, as in

obj = {

    'my_fn': function(arg1, arg2, arg3){
    //  Body of the function.
    }
};

but this is often best avoided.

JavaScript provides another method (called function declaration)

function my_fn(arg1, arg2, arg3){
    //  Body of the function.
};

which should (in the author’s view) never be used. It has strange properties [link].

Calling a function

There are four ways of calling a function in JavaScript. The difference involves Functions and this, which we’ve not covered yet. In brief, the four forms are:

x = my_fn(a, b, c);                // Simple function call.
x = obj.my_fn(a, b, c);            // Method  call.
x = my_fn.call(obj, a, b, c);      // Explicit this call.
x = my_fn.apply(obj, [a, b, c]);   // Explicit this apply.

For all forms of the function call, supplying the wrong number of arguments does not raise an error. Instead, excess arguments are ignored, and excess parameters are initialised to undefined.

Function call

This is the simplest form of function call.

x  = my_fn(a, b, c);

The this-object is set to the Global object (stub), which causes a problem only if the body of the function refers to this. Many functions are intended to be used in this way.

Method call

This is the usual, but not the most general, way of setting the this-object.

x  = obj.my_fn(a, b, c);       // Usual form.
x  = obj['my_fn'](a, b, c);    // Variant form.

The two forms are completely equivalent. The this-object is set to the obj.

The two following calls are always equivalent:

x  = a.b.c.d.e.my_fn(a, b, c);
tmp = a.b.c.d.e
x  = tmp.my_fn(a, b, c);

Method call gotcha

In JavaScript the two following calls are rarely equivalent:

x  = obj.my_fn(a, b, c);
tmp = obj.my_fn
x  = tmp(a, b, c);

whereas in Python they always are.

For JavaScript, in the first the this-object is obj while in the second it is the global-object. For explanation see [link].

Explicit this-call

Suppose obj is a JavaScript object. Then

x = my_fn.call(obj, a, b, c);

is equivalent to

x = my_fn(a, b, c);

except that the this-object is set to obj (rather than the global object). For more see [link].

Explicit this-apply

Suppose obj is a JavaScript object. Then

x = my_fn.apply(obj, [a, b, c]);

is equivalent to

x = my_fn(a, b, c);

except that the this-object is set to obj. For more see [link].

Explicit this gotcha

If obj is not a JavaScript object then in

x = my_fn.call(obj, a, b, c);
x = my_fn.apply(obj, [a, b, c]);

the this-object is set to the global object (which is probably not what you want). For more see [link].