# Module 5 : Functions

After completing Module 5, the student will:

* be able to declare and call functions;
    
* know how to pass call arguments to a function and return the result of its operation from it;
    
* understand the concept of a local variable and the effect of shadowing variables with the same names within a function;
    
* know that a function in JS is a first-class member and be able to take advantage of this by declaring functions using function expressions and passing functions as arguments to calls of other functions;
    
* understand the concept of recursion in the context of functions and be able to solve simple programming problems by using it;
    
* have a basic understanding of the callback function and be able to use it asynchronously in conjunction with the setTimeout and setInterval methods;
    
* have a clear understanding of arrow function notation and be able to write alternative functions as regular declarations, function expressions, and arrow functions.
    

---

* Function basics (what are functions, declaring functions, calling functions, local variables, the return statement, function parameters, shadowing)
    
* Functions as first-class members (function expressions, passing a function as a parameter, callbacks)
    
* Arrow functions (declaring and calling)
    

# Functions

Declaring functions at the beginning of the code is just good practice, not a JavaScript syntax requirement. Function declarations are automatically moved to the top of the scope, so we can use them before the declaration as long as they are in the scope. So,

```javascript
let name = Alice

function showName() {
    console.log(name);
}

showName(); // -> Alice
```

will work exactly the same as:

```javascript
let name = Alice

showName(); // -> Alice


function showName() {
    console.log(name);
}
```

# **Functions as first-class members**

This term means that functions can be treated as any data, which can be stored in variables or passed as arguments to other functions.

```javascript
function showMessage(message) {
    console.log('Message: ${message}');
}

let sm = showMessage; // showMessage function stored in variable sm
sm("This works!"); // -> Message: This works!
console.log(typeof sm); // -> function
```

This property is especially useful when passing the function as a call parameter to other functions.

```javascript
function add(a, b) {
    return a + b;
}

function multiply(a, b) {
    return a * b;
}

function operation(func, first, second) {
    return func(first, second);
}

console.log(operation(add, 10, 20)); // -> 30
console.log(operation(multiply, 10, 20)); // -> 200
```

# **Function expressions**

To store a function in a variable or pass it as an argument to call a function, you do not necessarily have to declare it previously and use its name. Below, we first declare the add function and then store it in the variable myAdd.

```javascript
function add(a, b) {
    return a + b;
}

let myAdd = add;
console.log(myAdd(10, 20));     // -> 30
console.log(add(10, 20));   // -> 30
```

Instead, we can shorten this notation and declare the add function, and at the same time store it in the myAdd variable. **This form of defining a function is called function expression.** In this case, it is specifically a named function expression, because the function has a name (add).

```javascript
let myAdd = function add(a, b) {
    return a + b;
}

console.log(myAdd(10, 20)); // -> 30
console.log(add(10, 20)); // -> 30
```

### anonymous function expression

For an anonymous function expression, simply remove the name following the function keyword to change the function to anonymous.

```javascript
let myAdd = function(a, b) {
    return a + b;
}
console.log(myAdd(10, 20)); // -> 30
```

This will be much more evident when passing a function as a call parameter to another function.

```javascript
function operation(func, first, second) {
    return func(first, second);
}

let myAdd = function(a, b) {
    return a + b;
}

console.log(operation(myAdd, 10, 20)); // -> 30

console.log(operation(function(a, b) {
    return a * b;
}, 10, 20)); // -> 200
```

It only gets interesting when we call the `operation` function again. **This time, the first argument is the anonymous function (again the function expression), which is defined directly in an operation call.** The result is a multiplication, although the name of the new function (or the variable in which it could be placed) will not appear anywhere. The function has been defined only to pass it once into the operation function. At first glance, it may look like a completely useless mechanism, but in the real world, it is used very often.

# Callback functions

* The simple meaning of a callback function is that it's a something-handler function for some event.
    
* A function that receives a callback as an argument can call it anytime.
    

## **Synchronous callbacks**

Subsequent instructions are executed in the order in which they are placed in the code. If you call a function, the instructions in it will be executed at the time of the call.

```javascript
let inner = function() {
    console.log('inner 1');
}

let outer = function(callback) {
    console.log('outer 1');
    callback();
    console.log('outer 2');
}

console.log('test 1');
outer(inner);
console.log('test 2');
```

Execution of the above code will cause the console to print out the following text in this exact order:

`test 1`  
`outer 1`  
`inner 1`  
`outer 2`  
`test 2`

# **Asynchronous callbacks**

Using appropriate functions, we combine a specific type of event with a selected callback function, which will be called when the event occurs.

One of the simplest cases when there is an asynchronous execution of instructions is the use of the `setTimeout` function. This function takes another function (a callback) and the time expressed in milliseconds as arguments. The callback function is executed after the specified time, and meanwhile, the next program instruction (placed in the code after `setTimeout`) will be executed.

Thus, the moment the callback function is called is not determined by its order, but by an arbitrarily imposed delay. The delay only applies to the callback function given to `setTimeout`, while the rest of the code is still executed synchronously.

```javascript
let inner = function() {
console.log('inner 1');
}

let outer = function(callback) {
console.log('outer 1');
setTimeout(callback, 1000) /*ms*/;
console.log('outer 2');
}

console.log('test 1');
outer(inner);
console.log('test 2');
```

The result is actually a bit different than we observed in the previous example :

`test 1`  
`outer 1`  
`outer 2`  
`test 2`  
`...`  
`inner 1`

**setTimeout and setInterval functions**

The `setTimeout` function is used when you want to cause a delayed action. A similar function is `setInterval`. This time, the action is also performed with a delay, but periodically, so it is repeated at fixed intervals. In the meantime, the main program is executed, and at every specified time, the callback given as an argument for a setInterval call is called.

Interestingly, the `setInterval` function returns an identifier during the call, which can be used to remove the timer used in it (and consequently to stop the cyclical callback function call). We will do this in the next example. First, we run `setInterval`, which will call the callback function (i.e. the `inner` function) in one-second intervals. Then we call `setTimeout`, which will turn off the timer associated with the previously called `setInterval` after 5.5 seconds. As a result, the `inner` function should be called five times. In the meantime, the rest of the program will be executed ...

```javascript
let inner = function() {
console.log('inner 1');
}

let outer = function(callback) {
    console.log('outer 1');
    let timerId = setInterval(callback, 1000) /*ms*/;
    console.log('outer 2');
    
    setTimeout(function(){
        clearInterval(timerId);
    }, 5500);
}

console.log('test 1');
outer(inner);
console.log('test 2');
```

`setInterval` is asynchronous and uses anonymous function expression (i.e. the `inner` function).

`setTimeout` is asynchronous and have anonymous function which is defined directly in an operation call.

output :

`outer 1`  
`outer 2`  
`test 2`  
`...`  
`inner 1`  
`inner 1`  
`inner 1`  
`inner 1`  
`inner 1`

Usually, however, asynchronous function calls are related to slightly different situations. They are determined by events not related to timers, but rather generated outside of the program. As we have said before, they can be, for example, actions performed by the user, such as a mouse click on an interface element on a page.

### addEventListener

The window in which this page is located is represented in the client-side JavaScript by a global window variable. The window object has a method named `addEventListener`. This function allows you to register a certain action to be performed in response to a window-related event. Such an event can be a "click", which is a single mouse click on any place on the page.

The action to be taken is passed to the addEventListener method as a callback function.

```javascript
window.addEventListener("click", function() {
    console.log("clicked!");
});
```

Nothing special should happen immediately after it is started. Only when you click anywhere on the page should a message appear on the console: "clicked!". Our function is not called until the "click" event occurs, which is absolutely asynchronous. In the meantime, between subsequent clicks, the rest of the program could be executed.

In fact, it is not a very good idea to connect a click response to a window object. Most often, such actions are associated with specific elements of the interface (buttons, checkboxes, etc.) which allow for their differentiation. This is only to demonstrate a function call with a user-generated event.

# **Arrow functions**

* An **arrow function** is a shorter form of a function expression.
    
* We can, therefore, assume that both ways of defining functions, i.e., function expression and arrow function expression, allow you to define identically working functions.
    

For example, the function add, which we already know:

```javascript
let add = function(a, b) {
    return a + b;
}
console.log(add(10, 20)); // -> 30
```

can be written as follows:

```javascript
let add = (a, b) => {
    return a + b;
}
console.log(add(10, 20)); // -> 30
```

or simplified even more (the function has only one statement, whose value returns):

```javascript
let add = (a, b) => a + b;
console.log(add(10, 20)); // -> 30
```

The arrow expression is mainly used for short functions, often anonymous, which can be presented as even more compact in this form. They differ from ordinary functions by one more thing apart from the form of notation, in other words, how the keyword `this` is interpreted inside them.

One typical example of using arrow functions is the `forEach` method, available in `Array` type data. The `forEach` method is another, and frankly speaking, currently the most used one. This method takes as an argument ... a function. This function will be called each time for each element of the array. We can create any function for this purpose. There is one condition, which is that it must have at least one parameter.

```javascript
let names = ['Alice', 'Eve', 'John'];
function showName(element) {
    console.log(element);
}
names.forEach(showName); // -> Alice, Eve, John
```

The `showName` function has been passed as a call argument to the `forEach` method of the names array. Therefore, `showName` will be called three times, for each element of the names array, and in each call its parameter will be equal to the successive name, i.e. in turn: `Alice`, `Eve` and `John`. The only thing `showName` has to do is to display the received `element` (name).

The same effect can be achieved by passing an anonymous arrow function to the forEach method.

```javascript
let names = ['Alice', 'Eve', 'John'];

names.forEach(a => console.log(a));
```

We do not even store it in a variable because we assume that we will use it only here and will not refer to it again.

# Summary

Third-party functions are usually made available in the form of libraries (i.e., sets of functions), which are dedicated to solving a specific class of problems, for example, Leaflet (maps), D3.js (data visualization), or jQuery (DOM manipulation).
