loading...

"for" vs. "forEach" and the value of documentation

Arit Amana on November 09, 2018

This post is a quick note to underscore how important it is for devs to get comfortable with documentation. Mind you, I'm the first one over on Sta... [Read Full]
markdown guide
 

You can do something more to keep this code structure, just a helper variable:

function greaterThan(numbr){
    let helper = false;

    array1.forEach(function(item){
        if (item >= numbr && !helper){
            helper = true;
        };
    });

    return helper;
};

But to keep the functional style that you want with forEach and stay in simple(readable?) code:

const greaterThan = (number) => array1.some((v) => v >= number)

Sometimes exists another method in the docs to get the goal that you want...

 
 

some method doesn't check the condition with every element present in the array it just returns true if one element satisfies the condition.

const array = [2,3,4,5];

function  greaterThan(number) {
 return  array.some((e) => e >= number)
}


console.log( greaterThan(1)); // true

Like in above code some method only checks the condition with first element in the array so it returns true .

There is a every method in javascript, it checks the condition with every element present in the array.

const array = [2,3,4,5];

function  greaterThan(number) {
 return  array.every((e) => e >= number)
}


console.log( greaterThan(1)); // true

References

 

If we break down the code, it is easier to see what is going on.

I'm gonna pull the function out of the forEach and create a new gte function.

function gte(a, b){
  if (a >= b){
    return true;
  };
  return false;
};

function greaterThan(numbr){
    array1.forEach(item => gte(numbr, item));
//                 ------------------------
//               /
// Now it's easier to see that this doesn't do anything.
    return false;
};

Array.forEach's first argument is a function. I would recommend always breaking the function out to make the code more understandable.

When written this way, it is more clear what is going on and that you would not expect the forEach to return a value from the outer function greaterThan.

I also agree with kip, the better way would be some or every since it will break early on a false and not iterate the entire array.

array1 = [2,3,4,5];
const greaterThan = numbr => array1.some(item => item >= numbr);

greaterThan(4); //=> true
greaterThan(9); //=> false
greaterThan(2); //=> true
greaterThan(1); //=> true
 
 

Shout out to the ReasonML and ReasonReact docs.

I built my entire project from blank file to production, starting with zero knowledge of Reason, without needing any resource at all outside of these two websites once. That's not something that happens too often.

 

I think it's helpful to understand why, regardless of what the forEach method actually does, the above couldn't work.
Even if we imagine that forEach short circuits on a truthy return value from the function passed in... and returns that value...
There's still no way that value would make it to the output of our greaterThan function.

const array1 = [2,3,4,5];
function equalOrGreaterThan(numbr){
    return array1.forEach(function(item){
        if (item >= numbr){
            return true;
        };
    })
    || false;
};

This would work (if that's what forEach did), since we are taking note of the return value. (The || false is there so that we know exactly what we're returning, not null or undefined)

Since the .findIndex() .find() .some() family of methods do exist, we can indeed do that:

const array1 = [2,3,4,5]
function equalOrGreaterThan(numbr){
    return array1.some(function(item){
        return item >= numbr
    })
}

Functions that have only one statement - a return statement, are also prime candidates to be arrow functions:

const array1 = [2,3,4,5]
const equalOrGreaterThan👌 = numbr =>
    array1.some(item => item >= numbr)
 

Finally, if doing this in real life, you probably want to avoid iterating on every check if the array is unchanged:

const equalOrGreaterThan👌 = array => {
    const max = Math.max(...array)
    return numbr => max >= numbr
}
const equalOrGreaterThan👌😂 = array => {
    let max = Math.max(...array)
    return {
        isIt: number => max >= numbr
        push: (...args) => { max = Math.max(max, ...args)}
    }
}
 

Wondering why you didn't use [12,3,44,5].find function for the same ?

function greaterThan(number) {
    return array1.find((item) => item > number ) !== undefined
}
 

In the example find is the solution that is the best description for the wanted behavior.

In general, if you "wanted perform some calculations on each item of an array", prefer map (a pure transformation of each object) over imperative for and forEach.

 

Totally agree . People who start programming, generally they start with the procedural paradigm of programming. for loop is one the first thing that people come across (along with if-else). That sticks to their mind forever , until functional programming is introduced to them . Its just matter of time to get used to such paradigm . I am pretty sure with few weeks, the author of the article will be very well versed in functional programming

 

What I'm loving about this thread is reading all the ways to accomplish my coding goal 😊 Thanks so much for your suggestion.

 

Because of this reason I joined dev.to recently .

Back to the arrays discussion, the trend of using for loop will go away.
For every use case there must be some array function available.

w3schools.com/jsref/jsref_obj_arra...

 

I see all the solutions in the comments, you can also do this with the filter method:

const greeterThan = num => array1.filter(n => n >= num).length > 0;

OR (basically the same)

function greeterThan(num) {
  return array1.filter(n => n >= num).length > 0;
}
 

Array.prototype.filter() is probably the least suitable here, for two reasons:
1) It allocates an output array.
2) Even if the very first element matches, it will still test all of the remaining elements.

In contrast, Array.prototype.some() only returns a boolean, and never executes the predicate past the first match. In other words, it implements the optimizations one would do in the for loop when does at least something match? is the question.

If you do care about the value, there's Array.prototype.find(), and if you actually need the key/index yourself, for example to replace the value in place or look up a matching index in another array, there's Array.prototype.findIndex()

 

And one thing to remember for interviews is that none of them returns a new array ( or iterable ) only Array.prototype.map() returns a new array or iterable

this has what confused me a lot in few of my interviews from those harsh 73 interviews.

 

filter returns a new array as well.
And in cases where it's used as a map+filter optimization, so does reduce (but not in other cases).

 

Idk, they're really easy to find, I don't have a specific source.
This seems adequate enough: medium.com/jsguru/javascript-funct...

 

can you please elaborate on this more or give some references articles/blogs to read from?

 

When I first started out using Angular, I developed a bias for its official documentation as it was very comprehensive.

 

Agree, I love how angular's docs written. The problem is Angular tries to cover a much broader set of problems, hence its overall harder for people and in the end, less popular.

 

This was originally in perldoc. I think it applies very generally if you take out the Perl-specific vocabulary:

(Almost any for or foreach construct) will get very confused if you add or remove elements to (what you're looping over) within the loop. So don't do that.

 

I like to think of it as forEach not returning a value at all, whether or not that's true. That helps to remind me that it's purely for side effects.

 

I usually refer to docs when I forget how a specific function works, or if I need to explore what certain objects can do.

 

This makes me appreciate even more the work a community puts into getting very good documentations in place. Eg: Vue.js, Laravel, etc.

 

I thought this tweet was pretty on-point

 
code of conduct - report abuse