Why use three parameters for this callback function?

-1

I'm learning JavaScript, and I was recreating the function type forEach (using a for loop) within prototype of an array . And for that I used a callback function, below:

Array.prototype.forEach2 = function (callback) {
    for (let i = 0; i < this.length; i++) {
        callback(this[i], i, this)
        // para uma função 'callback' você deve passar três parâmetros: 
    }
}

I want to understand why we have to pass 3 parameters to the callback functions, which are: value, index, and array     

asked by anonymous 02.09.2018 / 22:57

2 answers

1

Because JavaScript is a language in which you do not need to specify the type of data you expect to receive in the argument passed to the function (in this case you called the callback argument) the code that uses this argument needs to do this or an error may occur when it is using this argument.

In your code, you expect the callback argument to be a function variable, and this function receives 3 arguments: the array element, the array index, and the array itself. The code sets the signature this way because it was probably based on the forEach method code.

Why are you doing this? Because you expect the user of this forEach2 function to use it as follows: umArrayQualquer.forEach2(function (v, i, arr) { ... });

So, when used, the function will be passed in the callback argument and internally will call the function correctly.

JavaScript is smart enough that the user of your role can have a simpler signature like umArrayQualquer.forEach2(function (v) { ... }); and work without error on your calling code, but imagine that the user of your role does not use it that way . If it makes the call like this: umArrayQualquer.forEach2(123); . Instead of passing a function that expects 3 arguments, it passed a number. This will cause an error in your code.

Array.prototype.forEach2 = function (callback) {
    for (let i = 0; i < this.length; i++) {
        callback(this[i], i, this)
    }
}

var umArrayQualquer = [1, 3, 4];

console.log("com função completa");
umArrayQualquer.forEach2(function (v, i, arr) {
   console.log(v);
});

console.log("com função simplificada");
umArrayQualquer.forEach2(function (v) {
   console.log(v);
});

console.log("com argumento errado");
umArrayQualquer.forEach2(123);

For this reason, whenever you are extending a class it is important to make checks within the code to ensure that the user of your role does not cause an unforeseen error.

Array.prototype.forEach2 = function (callback) {
    if (typeof callback === 'function')
      for (let i = 0; i < this.length; i++) {
          callback(this[i], i, this)
      }
}

var umArrayQualquer = [1, 3, 4];

console.log("com função simplificada");
umArrayQualquer.forEach2(function (v) {
   console.log(v);
});

console.log("com argumento errado");
umArrayQualquer.forEach2(123);

Of course I put a very extreme example and as you probably would use your extension yourself, I would not make that kind of mistake when using it, but I put it here just to illustrate that it is important for you to do checks to avoid mistakes because of this lack of JavaScript typing.

Would you always have to do it this way, passing the same values that forEach receives? No. Because you are extending the Array class you can define the arguments the way you need to meet your need. If you are extending because your code is going to be used by other people, then it is interesting to stick to the default because the code user will expect a different version of a forEach to have similar usage characteristics.

The name you give to your role is also important. If you call forEach2 it is a good tip for anyone to use understand that is similar to forEach , and if you implement it with something completely different it will be disrupting who will use the function. So a hint is always that to extend an existing class try to study the class first, what methods it has and how they work, especially for you not to reinvent the wheel.

    
03.09.2018 / 14:51
3

You made the code, you have to explain why you want to pass 3 arguments.

You know that in order to use right you will have to pass functions that expect these 3 information and use them in an appropriate way.

You've probably read this somewhere. Whenever you learn from sources that do not say why you did that, you should understand that the font is bad.

And understand that creating abstractions without necessity is not advantageous, it is unnecessary. I'll understand what you're doing just to learn something else, but it's good to make it clear, even for other people not to fall into this trap.

What I can speculate is that you want to pass on the function to be called the constant data there, that is, the element being parsed in that step, its index and the object as a whole being parsed. In this way it gives a certain freedom for the function to do what is necessary. But a simple%% would be more useful.

I've speculated because I know the original for and that's what it does. And it is one of the worst functions of JS. You save some characters and lose performance and create complications if you need to modify the code, otherwise it is very easy to get confused with scope doing this (I see almost everyone else going wrong on this).

So the answer to this is that it passes these arguments because all this should not be done. When you do not know where you want to go, any way is good. Examples of learning should have a real motivator, even if it is a fictitious problem. Designing applications depends on context, without one or with a wrong one learns wrong.

    
02.09.2018 / 23:54