Why use three parameters for this`callback`function?

Asked

Viewed 145 times

-1

I’m learning Javascript, and I was recreating the type function forEach (wearing a bow tie for) inside prototype of a array. And for that I used a function callback, down 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 functions callback, which are: the value, the index, and the array complete.

  • 1

    You do not necessarily need to pass three parameters, you can pass as many (and which) you want, also you can pass only the ones you will use.

  • 1

    Thank you @Leonardosantos. E in this case the callback used three parameters because they are all attributes needed to return the loop value for (value, index, and Array itself), that?

2 answers

3

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

You know that there to use right will have to pass functions that await this 3 information and that use properly.

You probably read it somewhere. Whenever you learn from sources that don’t say why they did it, understand that the source is bad.

And understand that creating abstractions without necessity is not advantageous, this same is unnecessary. I’ll understand that you’re doing it just to learn something else, but it’s good to make it clear, until other people don’t fall into this trap.

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

I speculated because I know the forEach() original and that’s what it does. And it’s one of the worst JS functions. You save a few characters and lose performance and create complications if you need to modify the code, besides it is very easy to get confused with scope doing this (I see almost everyone getting it wrong).

So the answer to that is that you pass these arguments because all of this shouldn’t be done. When you don’t know where you’re going, any path will do. Examples of learning should have a real motivator, even if it’s a fictional problem. Designing applications depends on the context, without one or with a wrong learned wrong.

  • You really think, "Whenever you learn from sources that don’t say why they did it, understand that the source is bad."

  • Thanks for the return, @Maniero. The above example was a second part of the forEach, demonstrating that it could be reconstructed. Without first seeing the answer I had tried to reconstruct it with a function using a loop for, but I could not call this function that I created with the punctuation in the array (for example, "nameArray.nomadFunctioning..") simulating the array forEach. In the process I learned that using the prototype it would be possible to do this. But had not understood right the concept of function callback and its parameterization.

1


Since Javascript is a language where you don’t need to specify the type of data you expect to receive in the argument passed to the function (in this case you called the argument callback) the code that uses this argument needs to make this check or else an error may occur when it is using this argument.

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

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

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

Javascript is smart enough that the user of its function can have a simpler signature like umArrayQualquer.forEach2(function (v) { ... }); and work without error your code that makes the call, but imagine that the user of your function does not use it in this way. If he makes the call like this: umArrayQualquer.forEach2(123);. Instead of passing a function that expects 3 arguments, you 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 function 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 set a pretty extreme example and since you probably would make use of its extension yourself, you wouldn’t make that kind of mistake when using it, but I put it here just to illustrate that it is important you do checks to avoid errors because of this lack of Javascript typing.

You would need to always do so, passing the same values as the forEach gets? No. As you are extending the Array class you can set the arguments the way you need to suit your need. If you are extending because your code will be used by other people, then it is interesting to maintain the standard because the user of the code will expect a different version of a forEach has similar usage characteristics.

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

  • Perfect, @pagotti ! Your comments were very clear. I was able to understand concepts I hadn’t noticed before. Thanks for the reply.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.