JavaScript/Functions

A function is a block of code that solves a dedicated problem and returns the solution to the calling statement. The function exists in its own context. Hence, functions divide massive programs into smaller 'bricks' which structure the software as well as the software development process.

JavaScript supports the software development paradigm functional programming. Functions are a data type derived from Object; they can be bound to variables, passed as arguments, and returned from other functions, just as any other data type.

Declaration
Functions can be constructed in three main ways. The first version can be abbreviated further; see below.

The conventional way:

Construction via a variable and an expression:

Construction via the  operator (this version is a little cumbersome):

Invocation
For the declaration of functions, we have seen 3 variants. For their invocation, there are also 3 variants. The declarations and invocations are independent of each other and you can arbitrarily combine them.

The conventional invocation variant uses the function name followed by parenthesis. Within the parenthesis, there are the function's arguments, if any exist.

If the script runs in a browser, there are two more possibilities. They use the  object that is provided by the browser.

Hint: If you use the function name without the parenthesis, you will receive the function itself (the script), not any result of an invocation.

Hoisting
Functions are subject to 'hoisting'. This mechanism transfers the declaration of a function automatically to the top of its scope. As a consequence, you can call a function from an upper place in the source code than its declaration.

Immediately Invoked Function
So far, we have seen the two separate steps declaration and invocation. There is also a syntax variant that allows the combination of both. It is characterized by using parenthesis around the function declaration followed by  to invoke that declaration.

This syntax is known as a Immediately Invoked Function Expression (IIEF).

Arguments
When functions are called, the parameters from the declaration phase are replaced by the arguments of the call. In the above declarations, we used the variable name  as a parameter name. When calling the function, we mostly used the literal "Go" as the argument. At runtime, it replaces all occurrences of  in the function. The above examples demonstarte this technique.

Call-by-value
Such substitutions are done 'by value' and not 'by reference'. A copy of the argument's original value is passed to the function. If this copied value is changed within the function, the original value outside of the function is not changed.

For objects (all non-primitive data types), this 'call-by-value' has a - possibly - astonishing effect. If the function modifies a property of the object, this change is also seen outside.

When the example runs, it shows that after the invocation of, the changes made by the function are visible not only in the return value. Also, the properties of the original object  have changed. Why this; is it different from the behavior concerning primitive data types? No.

The function receives a copy of the reference to the object. Hence, within the function, the same object is referenced. The object itself exists only one time, but there are two (identical) references to the object. It does not make a difference whether the object's properties are modified by one reference or the other.

Another consequence is - and this may be intuitively the same as with primitive data types (?) - that the modification of the reference itself, e.g., by the creation of a new object, will not be visible in the outer routine. The reference to the new object is stored in the copy of the original reference. Now we have not only two references (with different values) but also two objects.

Note 1: The naming of this argument-passing technique is not used consistently across different languages. Sometimes it is called 'call-by-sharing'. Wikipedia gives an overview.

Note 2: The described consequences of JavaScript's argument-passing are comparable with the consequences of using the keyword, which declares a variable to be a constant. Such variables cannot be changed. Nevertheless, if they refer to an object, the object's properties can be changed.

Default values
If a function is invoked with fewer arguments than it contains parameters, the surplus parameters keep undefined. But you can define default values for this case by assigning a value within the function's signature. The missing parameters will get those as their default values.

Variable number of arguments
For some functions, it is 'normal' that they get involved with different numbers of arguments. For example, think of a function that shows names. and  must be given in any case, but it's also possible that an   or a   must be shown. JavaScript offers different possibilities to handle such situations.

Individual checks
The 'normal' parameters, as well as the additional parameters, can be checked to determine whether they contain a value or not.

Every single parameter that may not be given must be individually checked.

The 'rest' parameter
If the handling of the optional parameters is structurally identical, the code can be simplified by using the rest operator syntax - mostly in combination with a loop. The syntax of the feature consists of three dots in the function's signature - like in the spread syntax.

How does it work? As part of the function invocation, the JavaScript engine combines the given optional arguments into a single array. (Please note that the calling script does not use an array.) This array is given to the function as the last parameter.

The third and all following arguments of the call are collected into a single array that is available in the function as the last parameter. This allows the use of a loop and simplifies the function's source code.

The 'arguments' keyword
In accordance with other members of the C-family of programming languages, JavaScript offers the keyword  within functions. It is an Array-like object that contains all given arguments of a function call. You can loop over it or use its  property.

Its functionality is comparable with the above rest syntax. The main difference is that  contains all arguments, whereas the rest syntax affects not necessarily all arguments.

Return
The purpose of a function is to provide a solution of a dedicated problem. This solution is given back to the calling program by the  statement.

Its syntax is, where   is optional.

A function runs until it reaches such a  statement (, or an uncatched exception occurs, or behind the last statement). The  may be a simple variable of any data type like , or a complex expression like  , or is omitted entirely:.

If there is no  within the   statement, or if no   statement is reached at all,   is returned.

Arrow functions (=>)
Arrow functions are a compact alternative to the above-shown conventional function syntax. They abbreviate some language elements, omit others, and have only a few semantic distinctions in comparison to the original syntax.

They are always anonymous but can be assigned to a variable.

Here is one more example using an array. The  method loops over the array and produces one array-element after the next. This is put to the arrow function's single argument. The arrow function shows  together with a short text.

Other programming languages offer the concept of arrow functions under terms like anonymous functions or lambda expressions.

Recursive Invokations
Functions can call other functions. In real applications, this is often the case.

A particular situation occurs when they call themselves. This is called a recursive invokation. Of course, this implies the danger of infinite loops. You must change something in the arguments to avoid this hurdle.

Typically the need for such recursive calls arises when an application handles tree structures like bill of materials, a DOM tree, or genealogy information. Here we present the simple to implement mathematical problem of factorial computation.

The factorial is the product of all positive integers less than or equal to a certain number $$n$$, written as $$n!$$. For example, $$4! = 4 \times  3  \times  2  \times  1 = 24$$. It can be solved by a loop from $$1$$ to $$n$$, but there is also a recursive solution. The factorial of $$n$$ is the already computed factorial of $$(n - 1)$$ multiplied with $$n$$, or in formulas: $$n! = (n-1)! \times n$$. This thought leads to the correspondent recursive construction of the function:

As long as $$n$$ is greater than $$0$$, the script calls  again, but time with $$n-1$$ as the argument. Therefore the arguments converge to $$0$$. When $$0$$ is reached, this is the first time the  function is not called again. It returns the value of $$1$$. This number is multiplied by the next higher number from the previous invocation of. The result of the multiplication is returned to the previous invocation of, ... .

Exercises

 * ... are available on another page (click here).