What's a callback? How is the code run?

Hello there, can somebody explain to me what a callback is? Is it a keyword in JS or something?

Can somebody please explain to me how is the callback function being callback again and how does the sequence of the code work?
Also I’m actually not too sure what callback is? Is it an array or a function in this case?
Because I’m calling this[i] but isn’t this the callback I’m taking? I’m very confused.

UPDATE QUESTIONS:
Can one of you explain this. If this is the callback function, why do we take the length of it. I initially thought it was an array.
Why is it newArray.push(callback(this[i])); instead of just newArray.push(this[i]);

for (let i = 0; i < this.length; i++) {
    newArray.push(callback(this[i]));
 }

Below is my answer, it seems to be working but when I double check with the solution, my doesn’t seem pretty correct.
Your code so far


// The global variable
var s = [23, 65, 98, 5];

Array.prototype.myMap = function(callback) {
var newArray = [];
// Only change code below this line
for (let i = 0; i < this.length; i++) {
  newArray.push(this[i] * 2);
}
// Only change code above this line
return newArray;
};

var new_s = s.myMap(function(item) {
return item * 2;
});
//GIVEN SOLUTION
// The global Array
var s = [23, 65, 98, 5];

Array.prototype.myMap = function(callback) {
  var newArray = [];

  // Add your code below this line
  for (let i = 0; i < this.length; i++) {
    newArray.push(callback(this[i]));
  }
  // Add your code above this line

  return newArray;
};

var new_s = s.myMap(function(item) {
  return item * 2;
});
  **Your browser information:**

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15

Challenge: Implement map on a Prototype

Link to the challenge:

A callback function in javascript is a function which you pass to another function and is called by that function. In your example, the function youre passing to myMap accepts an argument which is indeed a callback function and not an array.

for example

function logSomething(){
  console.log("beep boop");
}

SetTimeout(logSomething, 1000);

In the above example, the “logSomething” function is the callback function because it is being “called back” by the setTimeout function automatically after 1 second passes.

here’s an awesome article on callback functions if you wanna learn more about them.

https://www.freecodecamp.org/news/what-is-a-callback-function-in-javascript/

Hope this helped! :slight_smile:

1 Like

The way the code is presented is bit hard to read, so let me rewrite the code as follows:

// The global variable
var s = [23, 65, 98, 5];

Array.prototype.myMap = function(callback) {
var newArray = [];
// Only change code below this line

// Only change code above this line
return newArray;
};

function double(x) {
  return 2 * x;
}

function negate(x) {
  return -x;
}

var new_s = s.myMap(double); //returns [46, 130, 196, 10] for sample s

var s2 = s.myMap(negate); //returns [-23, -65, -98, -5] for sample s

[/quote]
We are trying to implement our version of built-in map. The map function accepts any function that takes one argument, such as functions double and negate. I call the function we pass to map a converter (my personal terminology, not a standard). The map function goes over every element of this array and applies the converter to it. In other words, we call the converter function passing the elements as the arguments. So, when we pass double, myMap will create and return [double(23), double(65), double(98), double(5)]. When we pass negate, then we’re doing [negate(23), negate(65), negate(98), negate(5)].

The original code uses an anonymous function instead of named function as I did above.

It is common to call the functions passed to another function callbacks because they are “called back” by the receiving function. But don’t make any issue with the terminology. What’s important is to understand how the map function works.

Hi I understand so far your example but why does the answer has
newArray.push(callback(this[i]));
Why is the callback written inside? Does it mean mine is wrong?

for (let i = 0; i < this.length; i++) {
  newArray.push(this[i] * 2);
}

This is wrong because no matter which function we pass to myMap, it will always double ( * 2) the elements of the array. This just happens to ‘work’ only when the passed function is double.

Remember that we are passing a function to myMap like

const s1 = s.myMap(double);
const s2 = s.myMap(negate);

myMap is defined as

Array.prototype.myMap = function(callback) {

The parameter name is callback. This stands for the function we’re passing to myMap. So, when calling myMap with double, callback is the name we’re using locally to refer to the passed function double. We need to call this function for all elements of the array and push the result to the new array, and therefore, we have

 newArray.push(callback(this[i]));

What is going on here is no different from passing a value. For example, if we have

function fun(x) {
. . .
}

x will be 8 when the function is called fun(8) and x be 12 for fun(12) and so forth.

2 Likes

Thank you for the explanation I think I get it now. So just to be sure in this case with the below code

newArray.push(callback(this[i]));

callback is calling the function passed as argument (based on your example double/negate) and this[i] will be the array passed in the callback function?

And another question is why do we take the length of the function i < this.length instead of the length of the array passed in the callback function or does it mean the same?

this is not the function

The Array instance can be accessed in the myMap method using this .

1 Like

To be clear, callback is not a predefined keyword in JS, its simply a term we use to describe a function which is passed as an argument to another function.
The myMap we define, is actually a method of the Array prototype object. Method is another term(just like callback), which describes a function which is owned by an object. In our case, this object is the global Array prototype. This means whenever you have an array, it comes with its methods(which are part of the array prototype) and those methods you can call on the array, just like we can call .map(), .sort(), .includes() and so on. If you were to create your own custom object, you could also attach methods to it, to execute actions, more often associeted with it. This is where this keyword comes in the current context. Here this refers to the array we call the method on. Once we define our myMap on the Array.prototype, we can call it on any array. Like [1,2,3,4].myMap(...), or we could use [1,3,2,4].sort(). The sort() method is predefined for us, the myMap() method, we defined for ourselves. this in the callback refers to the array [1,2,3,4]. this.length would mean [1,2,3,4].length, this[3] would refer to the element in the array in index 3, which is ‘4’. callback(this[3]) would execute our callback with argument ‘4’, or callback(4) and return whatever the callback function is defined to do with that function. It could be function callback(n){ return n+1 } and when we do callback(4), it will return the value of ‘5’.

Clarification #1: What is a callback function?

A callback function is a function in a specific context; said context is when the function is passed as an argument to another function. (Examples below)

This is similar to saying “father” is a person in a specific context; said context is when the person is male and has a child.

It is also similar to saying “son” is a person in a specific context. You get the point…

Clarification #2: What is a function?

(No. I’m not underestimating your intelligence. This can actually be very confusing.)
Consider these examples:

//Obviously this is a function:
function isFunction(parameter) {
  return parameter;
}

//Also a function because `isFunction` is 
//assigned *without* being called to 
//`alsoFunction`:
let alsoFunction = isFunction;

//Not a function but a string, because
//`isFunction` is called and returned the
//string "a" which is assigned to
//`notFunction`:
let notFunction = isFunction("a");

//Also not a function, but a number; same
//reason as above:
let alsoNotFunction = alsoFunction(1);

Once you understand the above, try to understand these examples:

//Continue from the above...

function anotherFunction(parameter) {
  if (typeof parameter === 'function') {
    return parameter("foo");
  }
  return parameter;
}

anotherFunction(isFunction); //Returns "foo".
//`isFunction` is a callback function because:
// 1. `isFunction` is a function; and
// 2. `isFunction` is passed to `anotherFunction`
//    as an arguments.

anotherFunction(isFunction("bar")); //Returns "bar".
//`isFunction` is not a callback function,
//because `isFunction("bar")`, i.e. `isFunction`
//called, is not a function but a string, and
//therefore you are actually passing a string
//instead of a function to `anotherFunction`.

Clarification #3: What’s what in your code.

For easier understanding, I made slight changes to your code.
Read my comment:

var s = [23, 65, 98, 5];

//`whatAmI` here is a parameter and represents the (first)
//argument passed to `myMap`; you can name it whatever
//you want.
Array.prototype.myMap = function(whatAmI) {
  var newArray = [];
  //`this` in JS refers to the object that's calling the function.
  for (let i = 0; i < this.length; i++) {
    newArray.push(whatAmI(this[i]));
    //For `whatAmI(this[i])` to be valid syntax,
    //`whatAmI` must be a function.
  }
  return newArray;
};

//Obviously a function:
function aFunction(item) {
  return item * 2;
}

//`aFunction` is passed to `myMap` without
//being called as an argument, therefore
//`aFunction` (in this context) is a
//callback function:
var new_s = s.myMap(aFunction);
//`s` is the object that's calling `myMap`,
//therefore `this` in `myMap` in this case
//refers to the array `s`.
//PS: Every value in JS ultimately is an object.
1 Like

We are not really “passing” an array here. We are not defining a function that takes two arguments like

function myMapX(arr, func) {
 . . .
}

Rather we are defining a method for instances of the Array class.

Array.prototype.myMap(func) {
. . .
}

We use (call) this method as such

const xs = [1, 2, 3, 4, 5]
const ys = [10, 20]

const r1 = xs.myMap(double)
const r2 = ys.myMap(double)

We are calling myMap method of xs, passing double as an argument and also calling the same method of ys and passing the same argument. Notice the method myMap is working on different arrays.

The reserved word this is the mechanism to refer to an array on which the method is called on. In the first call, this is referring to xs and in the second call to ys. So this is just a stand in for whatever array which we’re calling the method on. The expression this.length is the length of the array the method is called on (xs, ys, etc.) and this[i] an i’th element of that array.

Make sense?

1 Like

Thanks to all who explain to me I finally understand it. ^^ Thanks so much!

Yes thank you so so much!

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.