DEV Community

Cover image for Enhance your JS Skill by using the correct array method
Code Oz
Code Oz

Posted on • Edited on

Enhance your JS Skill by using the correct array method

I saw a lot of junior developper using forEach when they need to handle array.

I will show you and help you to over-abuse of forEach by using the correct array methods depending on the current context!

forEach

When to use?

As I said before, you don't need to over-abuse of forEach. In some case forEach is a very good method.

If you need to iterate an array in order to make a specific action (for example console log each item).

You shouldn't use forEach every time you need to fill a new array (before doing this, check if you can use other methods)

👇

const items = [1, 2, 3, 4, 5]

items.forEach(item => console.log(item))
Enter fullscreen mode Exit fullscreen mode

forEach DOESN'T return any value !!

// 
// ...
const toto = items.forEach(item => console.log(item))
toto // undefined
Enter fullscreen mode Exit fullscreen mode

filter

When to use?

As named, it allow us to filter some value in your array depending on your condition.

Example 👇

For example if you want to remove odd number

❌ With forEach

const items = [1, 2, 3, 4]
const evenValue = []
items.forEach(item => {
   if (item % 2 == 0) {
      evenValue.push(item)
   }
})
Enter fullscreen mode Exit fullscreen mode

✅ With filter

const items = [1, 2, 3, 4]

const evenValue = items.filter(currentValue => {
   return currentValue % 2 == 0
})
Enter fullscreen mode Exit fullscreen mode

💡 When you are using filter you should return a boolean (the condition of filter) in each iteration. (otherwise JS Engine will coerce the returned value into boolean!)

map

When to use?

When you need to transform items from array to another array!

Example 👇

For example if you want to multiply all value in an array by 2.

❌ With forEach

const items = [1, 2, 3, 4]
const result = []
items.forEach(item => {
   result.push(item * 2)
})
Enter fullscreen mode Exit fullscreen mode

✅ With map

const items = [1, 2, 3, 4]
const result = items.map(item => {
   return item * 2
})
Enter fullscreen mode Exit fullscreen mode

💡 When you are using map you need to return an item (transformed item) in each iteration.

reduce

When to use?

When you need to get a single value from an array. This 'single value' can be an array.

Example 👇

For example if you want to sum all number in array.

❌ With forEach

const items = [1, 2, 3, 4]
let accumulator = 0

items.forEach(item => {
   accumulator += item
})
Enter fullscreen mode Exit fullscreen mode

✅ With reduce

const items = [1, 2, 3, 4]

const sum = items.reduce((accumulator, currentValue) => {
   return accumulator += currentValue
}, 0)
Enter fullscreen mode Exit fullscreen mode

💡 When you are using reduce you need to return the accumulator (value that is returned by the reduce method) in each iteration and you should also init this accumulator (in the example above we init the accumulator to 0)!

find

When to use?

When you need to find an item that fit a condition and you are using this item after.

const items = [1, 2, 3, 4]

const item = items.find(item => item === 3)

// ...

// Use item afterwards
Enter fullscreen mode Exit fullscreen mode

some

When to use?

If you need to check if one of you item match a condition (like find) but you don't need to use the item afterward.

Example 👇

For example if you want to check if you array has the number 2.

Using find is bad if you don't use item afterward, or you just use item for checking if the value is undefined or not (to know if the condition has matched)

❌ With find

const items = [1, 2, 3, 4]
const item = items.find(item => item === 2)
if (item !== undefined) {
   // ...
}
Enter fullscreen mode Exit fullscreen mode

✅ With some

const items = [1, 2, 3, 4]
const hasNumber2 = items.some(item => item === 2)
if (hasNumber2) {
   ...
}
Enter fullscreen mode Exit fullscreen mode

💡 some return boolean if at least one item matched your condition

every

When to use?

every is similar to some, it will check if ALL of your items match your condition. Instead of some that will return true if only one item match the condition, every will return true only if all items match the condition!

TLDR;

As you can see you can use a lot of array methods depending on the context, so you can avoid to over-abuse of forEach!

It's also a good point to use methods depending on the current context for other developers that will read you code (for example if I see filter I know that we need to filter a value from this array)

A good point that I didn't show above, it's about the fact that you can combining array methods (except forEach since forEach doesn't return value).

So you can make this 👇

You need to filter odd value from array and multiply event number by 2.

const items = [1, 2, 3, 4]

const result = items.filter(item => item % 2 == 0 ).map(item => item * 2)
Enter fullscreen mode Exit fullscreen mode

I hope you like this reading!

🎁 You can get my new book Underrated skills in javascript, make the difference for FREE if you follow me on Twitter and send message to me 😁 and SAVE 19$ 💵💵

Or get it HERE

🇫🇷🥖 For french developper you can check my YoutubeChannel

🎁 MY NEWSLETTER

☕️ You can SUPPORT MY WORKS 🙏

🏃‍♂️ You can follow me on 👇

🕊 Twitter : https://twitter.com/code__oz

👨‍💻 Github: https://github.com/Code-Oz

And you can mark 🔖 this article!

Top comments (24)

Collapse
 
jonrandy profile image
Jon Randy 🎖️

you need to init this accumulator

This is incorrect, you can omit the initial value for the accumulator. If you do this, the accumulator will be automatically initialised to the first item in the array, and the reduce will continue from the next item. Your example can therefore be written more efficiently as:

const items = [1, 2, 3, 4]

const sum = items.reduce((accumulator, currentValue) => {
   return accumulator += currentValue
})
Enter fullscreen mode Exit fullscreen mode
Collapse
 
codeoz profile image
Code Oz

Hey thanks for comment, in fact you but it's really not adice to not init your accumulator value!

I edtied the post about this fact thanks!

Collapse
 
jonrandy profile image
Jon Randy 🎖️

The ability to have the accumulator automatically initiated like this is a part of JS and allows for more efficient code. Telling people not to use it is bad advice. The same advice applies as per my other comment - how do you expect developers to improve at JS if there is an insistence on treating them as children who will not understand more than basic code. 'Readable' code is subjective, and should not come at the price of less efficient code, and the misleading of people who are learning.

Collapse
 
mariamemeel profile image
Mora Emeel

I was about to write this comment

Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

When you are using filter you need to return a boolean (the condition of filter) in each iteration

This isn't true. You can return anything you like - the value will be coerced to a boolean based upon its truthiness or falsiness. Examples:

const arr = [1, 2, 3, 4]
const evenNumbers = arr.filter(item => 1 & item ^ 1)   // [2, 4]
const oddNumbers = arr.filter(item => item % 2)   // [1, 3]
Enter fullscreen mode Exit fullscreen mode

Both of these filter functions return numbers, not booleans. Similarly, you could strip empty strings out of an array by just returning the string in the filter function:

const arr = ['aaa', '', 'bbb', 'ccc', '', '', 'ddd']
const nonEmptyStrings = arr.filter(item => item)   // ['aaa', 'bbb', 'ccc', 'ddd']
Enter fullscreen mode Exit fullscreen mode

This works because non-empty strings are truthy and empty strings are falsey

Collapse
 
codeoz profile image
Code Oz

hey yes you can but it's not totally clear for every dev that will read your code! I prefer the option of making a good return about a condition ! I edited the post to add your comment thanks

Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

If we want to make the code totally clear for every dev, then we need to write for the lowest common denominator of understanding... which is obviously a terrible idea since no developer will ever get any better, or understand how JS actually works

Thread Thread
 
sebalr profile image
Sebastian Larrieu

Coerce to boolean is a bad practice and you are not a better programmer because you use one less line of code, also developers that write clear code are not child

Thread Thread
 
jonrandy profile image
Jon Randy 🎖️ • Edited

I very much did not say they were children. I said that by misleading them and falsely telling them they have to do something - you are treating them like a child - assuming they cannot understand the language feature and make the choice for themselves. You are denying them knowledge, to preserve the dogma of 'clean' code

Thread Thread
 
jonrandy profile image
Jon Randy 🎖️ • Edited

From the MDN docs for filter:

Function is a predicate, to test each element of the array. Return a value that coerces to true to keep the element, or to false otherwise.

Thread Thread
 
sebalr profile image
Sebastian Larrieu

I know the docs, I know js and I know coertion, I also know this kind of things lead to bugs and thats why we have lint rules and typescript.
If you want to filter strings and abuse coertion you will lost one valid result from this array [null, '', 'valid'], just because one smart developer didnt want to write some extra text

Thread Thread
 
jonrandy profile image
Jon Randy 🎖️ • Edited

You should probably email Mozilla to get them to change their docs - they're condoning abuse!

Seriously though, there's nothing wrong with doing it if you understand the ramifications. Sure, you gave an example with a very particular situation where there might be an issue, but there are also times when you KNOW what data is going to be coming in, and can code appropriately.

Appropriate code for appropriate situations

Thread Thread
 
sebalr profile image
Sebastian Larrieu

The docs are fine because they reflect reality. But js has many parts that work in weird ways that should be avoid to write maintanible code and make life a little easier for the person that is working in your code after you

Thread Thread
 
jonrandy profile image
Jon Randy 🎖️ • Edited

If we always encourage developers to avoid the quirks, and sweep them under the carpet pretending they don't exist - knowledge of JS over the years will get progressively worse (something that I've actually seen happening over years of interviewing candidates), and you're denying the developers the chance to be better developers through a more complete understanding of the language. That is a bad idea. Learn about the quirks - learn why they're good, learn why they're bad, learn how they can help you, use them to your advantage when you can.

Collapse
 
thomasjunkos profile image
Thomas Junkツ

And then there is reduceRight which helped me a lot back in 2012 when we had input fields like customer.billingadress.street and had to parse that to {"customer":{"billingadress":{"street": $customer.billingadress.street.value}}}

Collapse
 
codeoz profile image
Code Oz

Nice usage of reduceRight!

Collapse
 
itsyuuto profile image
Yuuto

Thanks for this! Actually I use map

Collapse
 
renaudham profile image
renaudham

Hi.
Interesting because i tend to forget "some" and "reduce".
Anyway note that those functions has a slower performance, and forEach is not great also, than a for in...

Collapse
 
codeoz profile image
Code Oz

happy to help you ;D

Collapse
 
captflys profile image
CaptFlys

Nice!

Collapse
 
amk profile image
Amran AL Ketara

Nice article!
Can I post this in my blog and mention you in it ?

Collapse
 
codeoz profile image
Code Oz

hey sorry I can't accept! I will put it in my own blog and it's bad to copy the same article in many website for the SEO ;D

Collapse
 
amk profile image
Amran AL Ketara

🌹🌹

Collapse
 
codeoz profile image
Code Oz

Hey! I mean accumulator + currentValue but I use += since it will add current value to the current accumulator! it made the same thing but it return the accumulator directly!