> For the complete documentation index, see [llms.txt](https://bryan-guner.gitbook.io/my-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bryan-guner.gitbook.io/my-docs/array-methods-lesson/background/callback-functions.md).

# Callback Functions

**Callbacks and higher-order functions** are some of the most misunderstood concepts in JavaScript. In this post, we will become familiar with them to write pro-level code as JavaScript engineers.

**A callback function** is a function passed into another function as an argument, which is then invoked inside the outer function to complete some sort action.

### **Callbacks: Using a Function as an Argument**

**What is a callback?**

* A **`callback`** is always a function that is being passed into another function.

```js
let foobar = function (callback) {
  console.log("foo");
  callback();
  console.log("bar");
};

let sayHello = function () {
  console.log("hello");
};

foobar(sayHello); // prints
// foo
// hello
// bar
```

* Although we named our parameter *callback*, we could name it anything we like.

```js
let foobar = function (callback) {
  console.log("foo");
  callback();
  console.log("bar");
};

foobar(function () {
  console.log("hello");
}); // prints
// foo
// hello
// bar
```

* **`Anonymous Callback`** : When we use a function expression directly.
* Typically we want to assign our callback to a name if we plan on using it multiple times, an anonymous callball is better if it's just single use.

**A More Interesting Example**

```js
let add = function (num1, num2, cb) {
  let sum = num1 + num2;
  let result = cb(sum);
  return result;
};

let double = function (num) {
  return num * 2;
};

console.log(add(2, 3, double)); // 10
```

* **Variable expression function** being passed in as an argument.

```js
let add = function (num1, num2, cb) {
  let sum = num1 + num2;
  let result = cb(sum);
  return result;
};

console.log(add(60, 4, Math.sqrt)); // 8
```

* **`Math.sqrt`** built in function being passed directly in as an argument.

**Refactoring for an Optional Callback**

* We can add in a conditional to make the callback optional. (This is a very common pattern in Javascript!)

```js
let add = function (num1, num2, cb) {
  if (cb === undefined) {
    return num1 + num2;
  } else {
    return cb(num1 + num2);
  }
};

console.log(add(9, 40)); // 49
console.log(add(9, 40, Math.sqrt)); // 7
```

***

### **Callback Functions as First Class Objects**

* **`First-Class Object`** : A type that supports the same basic operations as most other types. (i.e. Numbers, Strings & Booleans)
* First-Class Objects must be able to do **three things**:
  * They can be stored in variables.
    * Function Expression Notation.
  * They can be passed as arguments.
    * Callback Functions.
  * They can be returned in functions.

    ```js
    function foo() {
      return function () {
        return "I'm a cat";
      };
    }
    ```
* As we have just proved above, functions are indeed first-class objects!
* **`Higher-Order Function`** : A function that should either accept another function as an argument, or return a function as an output.
* Callback Functions are passed into Higher-Order Functions.

***

### **Callback Functions Demo**

Interesting Interaction.

```js
let foo = function () {
  let bar = function () {
    console.log("interesting");
  };
  return bar;
};

console.log(foo()); // [function: bar]

let res = foo();
console.log(rest); // interesting.
```

## **Objectives**

### **Callbacks**

Given multiple plausible reasons, identify why functions are called “First Class Objects” in JavaScript. Given a code snippet containing an anonymous callback, a named callback, and multiple console.logs, predict what will be printed Write a function that takes in a value and two callbacks. The function should return the result of the callback that is greater. Write a function, myMap, that takes in an array and a callback as arguments. The function should mimic the behavior of Array#map. Write a function, myFilter, that takes in an array and a callback as arguments. The function should mimic the behavior of Array#filter. Write a function, myEvery, that takes in an array and a callback as arguments. The function should mimic the behavior of Array#every.

```javascript
// 1. Given multiple plausible reasons, identify why functions are called "First Class Objects" in JavaScript.
// Here are some of the reasons:
// A function is an instance of the Object type
// You can store the function in a variable
let negate = function (num) {
return num _ -1;
};
// You can pass the function as a parameter to another function
function player(callback) {
console.log('Lebron');
callback();
}
player(function () {
console.log('Los Angeles');
});
// You can return the function from a function
function sport() {
return (function team() {
return "I'm a returned function"
})
}
let newFunc = sport();
console.log(newFunc())
// 2. Given a code snippet containing an anonymous callback, a named callback, and multiple console.logs, predict what will be printed
function player(callback) {
console.log('Lebron');
callback();
}
function sport() {
console.log('Basketball');
}
const teamInfo = function () {
console.log('Lakers');
sport();
player(sport);
player(function () {
console.log('Los Angeles');
});
console.log('California');
};
teamInfo();
// 3. Write a function that takes in a value and two callbacks. The function should return the result of the callback that is greater.
function greaterValue(value, cb1, cb2) {
// compare cb1 invoked with value to cb2 invoked with value
// return the greater result
let res1 = cb1(value);
let res2 = cb2(value);
if (res1 > res2) {
// if this is false, we move out of if statement
return res1;
}
return res2;
}
let negate = function (num) {
return num _ -1;
};
let addOne = function (num) {
return num + 1;
};
console.log(greaterValue(3, negate, addOne));
console.log(greaterValue(-2, negate, addOne));
// 4. Write a function, myMap, that takes in an array and a callback as arguments. The function should mimic the behavior of Array#map.
function myMap(arr, callback) {
// iterate through the array, perform the cb on each element
// return a new array with those new values
let mapped = [];
for (let i = 0; i < arr.length; i++) {
// remember that map passes three args with each element.
let val = callback(arr[i], i, arr);
mapped.push(val);
}
return mapped;
}
let double = function (num) {
return num _ 2;
};
console.log(myMap([1, 2, 3], double));
// 5. Write a function, myFilter, that takes in an array and a callback as arguments. The function should mimic the behavior of Array#filter.
function myFilter(arr, callback) {
let filtered = [];
for (let i = 0; i < arr.length; i++) {
let element = arr[i];
if (callback(element, i, arr)) {
filtered.push(element);
}
}
return filtered;
}
// 6. Write a function, myEvery, that takes in an array and a callback as arguments. The function should mimic the behavior of Array#every.
function myEvery(arr, callback) {
for (let i = 0; i < arr.length; i++) {
let element = arr[i];
if (callback(element, i, arr) === false) {
return false;
}
}
return true;
}
// Initialize calculation functions to variables to put in array.
let add = function (n1, n2) {
return n1 + n2;
};
let subtract = function (n1, n2) {
return n1 - n2;
};
let multiply = function (n1, n2) {
return n1 _ n2;
};
let divide = function (n1, n2) {
return n1 / n2;
};
let mod = function (n1, n2) {
return n1 % n2;
};
let isDivisible = function (n1, n2) {
if (mod(n1, n2) === 0) {
return true;
}
return false;
};
// Initialize array containing calculation functions
let funcArray = [add, subtract, multiply, divide, mod, isDivisible];
// Initialize function taking two numbers and an array
// of functions as parameters
let calculateAll = function (n1, n2, arrayOfFuncs) {
let ansArray = [];
arrayOfFuncs.forEach(function (callback) {
ansArray.push(callback(n1, n2));
});
return ansArray;
};
// Initialize a function taking two numbers, an array
// of functions, and a users choice of which to call
// as parameters
let calculateChosen = function (n1, n2, arrayOfFuncs, choice) {
return arrayOfFuncs[choice](n1, n2);
};
// Call the function, passing in 10, 2, and an
// array of functions
console.log(calculateAll(10, 2, funcArray));
// Call the function, passing in 10, 2, and the
// users choice of operation
console.log(calculateChosen(10, 2, funcArray, 1));
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bryan-guner.gitbook.io/my-docs/array-methods-lesson/background/callback-functions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
