Callbacks & Higher Order Functions in JavaScript
Tags: javascript, functional, webdev, programming
Published: 2021-12-29 14:42:08

###### Photo by [Priscilla Du Preez](https://unsplash.com/@priscilladupreez?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/call-me-back-later?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
---
Javascript’s **functional programming** just like any other functional programming language like Common Lisp, Clojure, Elixir, OCaml, and Haskell is the idea that programs can construct programs by composing functions and applying them. Declaratively, we can write function definitions as trees of expressions that map values to other values, rather than a sequence of imperative statements which update the running state of the program.

JS treats functions as first-class citizens, meaning that they can be bound to names (including local identifiers), passed as arguments, and returned from other functions, just as any other data type can. This allows programs to be written in a declarative and composable style, where small functions are combined in a modular manner. One of the main concepts of functional programming which is the topic in discussion of this post is Callbacks & higher order functions.

To begin, we are going to examine a simple, regular and profoundly useless function that squares the number `3`.
```jsx
function () {
	return 3 * 3;
}
```
This is stupid and defies the fundamentals of functions and why we use them. There is no variability or reuse that we can get out of it. We can't use it to square another number or get a different value out of it. Not good!

So what we can do to make the function more reusable is generalize it taking the hard-coded number out and leaving that up to whoever calls the function to assign the number as input to the function they want to square.
```jsx
function squareNum (num) {
	return num * num
}
```
Now, we are deciding what data to apply our multiplication functionality to; only when we run our function, not when we define it. Let’s also see why we may not want to decide exactly what our functionality is until we run our function. Making our functionality reusable is the essence of why we have our higher order functions

Let's stretch the study of callbacks and higher-order functions idea by examining these functions:

```jsx
function copyArrayAndMultiplyBy2 (array) {
	const output = [];
	for (let i = 0; i < array.length; i++) {
		output.push(array[i] * 2);
	}
	return output;
}

function copyArrayAndDivideBy2 (array) {
	const output = [];
	for (let i = 0; i < array.length; i++) {
		output.push(array[i] / 2);
	}
	return output;
}

function copyArrayAndAdd3 (array) {
	const output = [];
	for (let i = 0; i < array.length; i++) {
		output.push(array[i] + 3);
	}
	return output;
}

const myArray = [1, 2, 3];
copyArrayAndMultiplyBy2 (myArray); // [2, 4, 6]
copyArrayAndDivideBy2 (myArray);   // [0.5., 1, 1.5]
copyArrayAndAdd3 (myArray);        // [4, 5, 6]
```
The functions above are very similar, the only difference is how the loop works either multiplying, dividing or adding to each element in the array. This code isn’t DRY, we are repeating ourselves.

What we can do to get better functionality and re-usability out of the previous code is by generalizing the function like we did before. We can have a generic MAMA function called `copyArrayAndManipulate` that takes not only `array` as an input but also a BABY function we are going to call (`instructions`). This way, we can break out all the little parts that are different in the functions above and have ONE mama function for all the redundant code. DRY!

```jsx
function multiplyBy2 (input) {
	return input * 2
}

function divideBy2 (input) {
	return input / 2
}

function add3 (input) {
	return input + 3);
}

function copyArrayAndManipulate (array, instructions) {
	const output = [];
	for (let i = 0; i < array.length; i++) {
		output.push(instructions(array[i]));
	}
	return output;
}

let result = copyArrayAndManipulate([1,2,3], multiplyBy2);
let result = copyArrayAndManipulate([1,2,3], divideBy2);
let result = copyArrayAndManipulate([1,2,3], add3);
```

Before we go any further with this article, there are a couple of points to agree on regarding JavaScript:
1. When thinking about code in JS, think in terms of **values** and not so much as labels or names of functions or variable.
![variables and values](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lmx13bb1s0l9zouh4x82.png)

2. The `Global Scope`, AKA `global memory` AKA `global execution context` AKA `Global thread`, is the default scope when we run any JS code in the browser or in node.
![global memory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3zglm1f2kg4cjb21g97l.png)
**side note: the global scope is called (window) in the browser and (global) in node.

3. Functions have their own scope called the `function scope`, AKA `function local memory`, `function execution context`.
![function local memory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aa1gwuwqqwcv5vy7uhrj.png)

4. The `call stack` runs the `global memory` and stacks invoked functions on top of the stack in the order they were called in our code. Like a stack of plates, we are only concerned with the top of the stack
![the call stack](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xmftuh7byx0injhatey4.png)

5. Functions in JS have 2 parts:
  * A **label**: the name of the function and
  * The **code** that is assigned to the label
  ![function parts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2mnslt3hmc963y8oqcr4.png)

Now that we got that out of the way, let’s walk through the code above line-by-line to better understand what happens when we call the mama `copyArrayAndManipulate` with one of the baby functions, say `multiplyBy2`:
```jsx
function copyArrayAndManipulate (array, instructions) {
	const output = [];
	for (let i = 0; i < array.length; i++) {
		output.push(instructions(array[i]));
	}
	return output;
}

function multiplyBy2 (input) { return input * 2 }

let result = copyArrayAndManipulate([1,2,3], multiplyBy2);
```
First, we declare a function definition into the global execution context (global memory) called `copyArrayAndManipulate`. *Note that we don’t run the code inside the function yet until it’s called.*
![copy Array And Manipulate function definition](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ufr4ty6xe48hacbop1jq.png)

Then, we declare a function definition into the global execution context (global memory) called `multiplyBy2`. *Note that we don’t run the code inside the function yet until it’s called.*
![multiply by 2 function definition](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q73qur0s0n0lbotiixg4.png)

In the last line, we declare a variable definition into the global execution context called `result` which is `undefined` for now until the function `copyArrayAndManipulate` is run and returns a `value` to be assigned to `result`
![The result variable declaration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dnwg2go3izxa4sh12o9i.png)

Since we called the `copyArrayAndManipulate` when defining the `result` variable, we need to run it and the returned value to be stores in the `result` variable and so we start by running the code inside of it and go into its `local function memory`
```jsx
function copyArrayAndManipulate (array, instructions) {
	const output = [];
	for (let i = 0; i < array.length; i++) {
		output.push(instructions(array[i]));
	}
	return output;
}
```
Let’s try to simulate what happens in the local memory of the `copyArrayAndManipulate` function:
![copy array and manipulate function's local memory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ctk43ccmmyyb7bd418a.png)

1. We assign a local function input/variable called `array` to the `value [1, 2, 3]`
![copy array and manipulate function's local memory array input](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wgvs0exfr644a5ykdpty.png)
![copy array and manipulate function's local memory array input code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fv19mkunine961b4ki94.png)

2. We assign a local function input/variable called `instructions` to the function definition **(not label)** of the function previously know as `multiplyBy2`.

![copy array and manipulate function's local memory instruction function as input](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d36dm2f5gjdyavi7v3b5.png)

![copy array and manipulate function's local memory instruction function as input code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1zokk3it411fj9iay3sa.png)

3. We initialize and assign a local function variable called `output` to the `value []` —empty array
![copy array and manipulate function's local memory output variable](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xxkfhxu6ikhfuvrshchf.png)
![copy array and manipulate function's local memory output variable code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uu75kmnmfghoc4kjfxvf.png)

4. Next we iterate through the `array[1, 2, 3]` using the `for..loop`. Note that `instructions(array[i])` function is called in the this step inside the `for..loop`.
![copy array and manipulate function's local memory loop](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pavl8px0g2x1n8mblg8x.png)

This means 2 things:

* We are going to are going to populate the array through `output.push`, calling the `instructions()` function 3 times, once for each element in the array.

* The call stack is going to have the `instructions()` function run 3 times once per array element. It will run, populate the array with the returned value and get deleted (garbage collected).

We we call the `instructions` function which is now equal to the `multipleBy2` definition (not the label) meaning it has its same code, we enter its own execution context:

```jsx
function multiplyBy2 (input) {
	return input * 2
}
```
* starts and begin with `i = 0`, `array[0] = 1`, and `1 * 2 = 2` the execution context of `multipleBy2` ends and so it is removed/deleted from the call stack. `2` is returned and pushed into the `output` array `output = [2]`

**First iteration**: calls the instruction function  with the `input: 1`, the function is now on top of the call stack:
![copy array and manipulate function's local memory loop 1st iteration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ve6ajibczh6klc3cdtbi.png)

**Second iteration**: calls the instruction function  with the `input: 2`, the function is now again on top of the call stack:
![copy array and manipulate function's local memory loop 2nd iteration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/93706ekvozzrr4mvos7s.png)

**Third iteration**: calls the instruction function  with the `input: 3`, the function is now again on top of the call stack:
![copy array and manipulate function's local memory loop 2nd iteration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/grcoi3efsn1bjy8qpwal.png)

* loop ends with the value `array [2, 4, 6]` which will be assigned to the `output` array constant and we exit the copyArrayAndManipulate function local memory back out to global memory
![copy array and manipulate function's local memory loop end and return saved to output array](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0acw6ru9qvylhu0d6wc6.png)

Finally, the value `[2,4,6]` is saved into the global variable value `result`
![the output array is saved to the global variable result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8i2i9o8nughb2ixj9iwk.png)

### How was this possible?

Functions in javascript are first-class objects. They can co-exist and can be treated like any other JS object:

1. they can be assigned to variables and/or properties of other objects
2. passed as arguments into other functions
3. returned as value from other functions (closure)

Functions have one property that JS objects do not have, **they can be invoked/called/run.** 

In the example above: `copyArrayAndManipulate` is our **higher order function**. takes in a function and passes out a function call `multiplyBy2` which is our **callback function**

```jsx
copyArrayAndManipulate([1,2,3], multiplyBy2);
```

**callbacks & higher order functions keep our code simple and DRY. lots of the underlying javascript powerful that allows us to run complex things like asynchronous code rely on this concept.**

###sources:
* [Wikipedia's Functional Programming](https://en.wikipedia.org/wiki/Functional_programming)
* [CodeSmith's YouTube channel 👌🏼
](https://www.youtube.com/watch?v=viQz4nUUnpw)