On the implementation of some() and Every()

Asked

Viewed 73 times

10

I’m trying to understand how the implementation of some() and every(), but I did not understand very well the two implementation algorithms.

  • some():

    Array.prototype.mySome = function(callback, context) {
     for (var i = 0; i < this.length; i++) {
        if (callback.call(context, this[i], i, this))
            return true;
    }
    return false;
    };
    
  • every():

    Array.prototype.myEvery = function(callback, context) {
     for (var i = 0; i < this.length; i++) {
        if (!callback.call(context, this[i], i, this))
            return false;
     }
     return true;
     };
    

My question is about how the if of both implementations work:

if (!callback.call(context, this[i], i, this))

I didn’t find anything about it in the documentation. What is that if returns and why he returns it?

2 answers

10


The way he calls the method callback in the implementation may seem a little strange. It does all this by the way Javascript handles the context (this). And he does it so that the context is maintained.

// [1]   [2]  [3]      [4]      [5][6]
callback.call(context, this[i], i, this)

Studying the code

Let’s unblock:

1. Variable callback

This callback is a predicate, ie, a function that returns true or false. For example:

const isVegetarian = (food) => !food.containsMeat;
[, , ].filter(isVegetarian);
// resultado: []

See that in the example, isVegetarian is the predicate. A function that returns true to vegan foods, or false to the contrary. The method Array.filter asks for a predicate, which is the function that will define the filter.

So much Array.some how much Array.every use a predicate. A function that will tell if the item in the list matches a certain rule.

2. Method call

In Javascript, there are three ways to call a function:

  1. minhaFuncao(x, y, z), which is the most common
  2. minhaFuncao.call(this, x, y, z), that allows changing the context (this)
  3. minhaFuncao.call(this, [x, y, z]), which allows you to modify the context and pass arguments as an Array

In the example given, the Function.call.

3. Context

This argument is the context in which the function will be executed. It is who will be returned when calling this, inside the predicate.

4. this[i]

Within the context of this function, the this is the instance of Array, since this method is a method of Array. By calling this[i], it is defining the first argument of the predicate function as the array item. And this runs for all items, or until the loop is interrupted.

5. i

In this implementation, the loop index is passed as the second argument of the predicate function. See:

const predicado = function (str, i) {
  console.log(i);
  return str.startsWith("a");
};

["avião", "ana", "alemanha"].every(predicado);

6. this

And as the third argument of the predicate function, the Array is past. See:

const predicado = function (str, i, arr) {
  console.log(arr);
  return str.startsWith("a");
};

["avião", "ana", "alemanha"].every(predicado);

  • In the last example it was not for the predicate to use the constant letra ?

9

Some means "some", so it will return immediately if any item is found (true):

if (callback.call(context, this[i], i, this))
   return true;

Every means "each", "all of a list", that is, if you find one that is not expected, it returns immediately (false):

if (!callback.call(context, this[i], i, this))
   return false;

In short, some to see if there are any items on the list that are expected, and every to know if all items are as expected.

Browser other questions tagged

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