Published on December 12, 2019

By Charles Odili

Developer and author at DigitalOcean.

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

ES5 and ES6 brought many changes to JavaScript, including better ways of working with a collection of data expressed as arrays. While the language has significantly improved support for declarative data manipulation on arrays and many modern browsers support them, only a limited subset of array capabilities are commonly used. In particular, the `.every()`

and `.some()`

functions can improve how developers manipulate arrays, and potentially give them performance gains.

This article will show that the prominent JavaScript array functions are `.map()`

, `.filter()`

, and `.reduce()`

, and will then go through examples of instances in which `.every()`

and `.some()`

would save computing power over the more prominent solutions.

`.map()`

, `.filter()`

, and `.reduce()`

: The Prominent JavaScript Array FunctionsUsage of `.map()`

, `.filter()`

, and `.reduce()`

are very common. For the purpose of this article, let’s call these three functions **MFR**.

These functions have gained more prominence over the other functions for manipulating array data in JavaScript. **Google Trends**, for example, shows more active searches for **MFR** than a sampling of other functions:

**Google Search** also shows that search queries for **MFR** produce far more results.

Search results for `.filter()`

are as much as over 74M. This is 99.97% higher than results for `.every()`

, and 99.98% higher than results for .`some()`

. This means people are talking, writing, and teaching more **MFR**, which suggests more usage over time.

`.every()`

and `.some()`

In JavaScript, it is generally taught to limit computations on arrays to iteration (.forEach) and transformation (.map, .filter, .reduce - a.k.a **MFR**) operations. This could lead to computations that could be done with `.some()`

or `.every()`

to be forced into **MFR** , especially a sequence of `.filter()`

followed by a .`reduce()`

.

Almost every usage of **MFR** where you need to exit early and not comb through the entire collection is a prime candidate for `.some()`

or `.every()`

, because they both short-circuit and exit the array iteration as early as possible, instead of running till the end and potentially wasting compute resources.

In a time when we are building more complex apps and shipping more bytes to the client, resulting in significant overhead to parse JavaScript (see TTI, anything we can do to have three iterations (due to short-circuit) instead of thirty is highly welcome.

`Array.prototype.every()`

The `every()`

method allows us to establish if *every* element within an array meets a certain requirement. It stops evaluating the array (short circuits) the first time it finds an element that does not satisfy the given requirement.

`Array.prototype.some()`

The `some()`

method allows us to establish if *some* (at least one) elements within an array meets a certain requirement. It stops evaluating the array (short circuits) the first time it finds an element that does satisfy the given requirement.

Let’s say you have been asked to write a simple `add()`

function to add a bunch of integers. The function should expect to be given any number of integers to be added and it should return their sum after computing the addition.

The following are two ways to complete this task.

If the add() function is given mixed input (e.g, integers, floats, undefined, strings, etc.), it should proceed with just the integers and return the sum from adding them. We could implement our add() function this way:

```
const add = (...entries) => {
return entries
.filter(Number.isInteger)
.reduce((sum, int) => {
return sum + int;
}, 0);
};
```

Since this scenario expects the `add()`

function to compute the sum from whatever integers exists within the given inputs, one might implement the function like we have in the previous code block. We first use `.filter()`

to extract only the integers and then compute the sum with a `.reduce()`

. The `.filter()`

operation will however iterate over the entire array even if there are no integers within it, wasting compute resources.

One can also argue that we can get a better solution like this:

```
const add = (...entries) => {
return entries.reduce((sum, entry) => {
if(Number.isInteger(entry)) {
return sum + entry;
}
return sum;
}, 0);
};
```

This take on `add()`

is a little better because, unlike the first one that iterates to identify valid data and then further iterates to compute the result based on the valid data, now there is just one block of iteration. However, we are still running through to the end of the array even if there might be no integers within it.

We need a way to first tell if the gathered inputs have at least one integer. Since we are trying to find the sum from the inputs, we actually need at least two integers in there. We will proceed to reduce the inputs to the sum of the integers if we can find two or more integers.

Lets use `.some()`

so ensure this condition is met:

```
const add = (...entries) => {
let theSum = 0;
if(hasTwoOrMoreInts(entries)){
// there are >= 2 integers, lets sum them
theSum = entries.reduce((sum, entry) => {
if(Number.isInteger(entry)) {
return sum + entry;
}
return sum;
}, 0);
}
return theSum;
};
```

Now we have a condition that prevents the sum calculation unless we are sure there are two or more integers. We are doing this with a `hasTwoOrMoreInts()`

function that we will be creating in the following:

```
const hasTwoOrMoreInts = (entries) => {
let lastIndex = -1;
let hasMinimumIntsCount = false;
const hasAnInt = entries.some((entry, index) => {
lastIndex = index;
return Number.isInteger(entry);
});
if(hasAnInt === true) {
// we've got one int, is there another?
const hasMoreInts = entries.slice(lastIndex + 1).some(Number.isInteger);
hasMinimumIntsCount = (hasMoreInts === true) && hasAnInt;
}
return hasMinimumIntsCount;
};
```

If the `add()`

function can receive mixed input (such as integers, floats, undefined, strings, etc.) but needs to only proceed with computing the sum of the given inputs if all the inputs are integers, a common approach influenced by the prominence of MFR might look like this:

```
const add = (...entries) => {
let theSum = 0;
const nonInts = entries.filter(entry => !Number.isInteger(entry));
if(nonInts.length === 0) { // are there non-ints?
theSum = entries.reduce((sum, int) => {
return sum + int;
}, 0);
}
return theSum;
}
```

Again `entries.filter()`

attempts to see if there are invalid inputs by iterating the entire `entries`

array to gather every input that is not an integer. If there are no invalid inputs (`nonInts.length === 0`

), we compute the sum with `.reduce()`

. This would have made sense if we needed the total number of all invalid inputs or all the inputs themselves. Otherwise, we should be looking for the first invalid input and deciding what to do next from there.

Like `.some()`

, `.every()`

will act on the least information necessary. In this case, once it finds an input that is not an integer, it will look no further (by exiting with a return of `false`

) and allow us to proceed with the next important thing.

Let’s see how `.every()`

does this for us:

```
const add = (...entries) => {
let theSum = 0;
const areAllInts = entries.every(Number.isInteger);
if(areAllInts === true) { // are these indeed all ints?
theSum = entries.reduce((sum, int) => {
return sum + int;
}, 0);
}
return theSum;
};
```

Since `entries.every()`

will return `false`

as soon as it finds what is not an integer, we are able to exit further tests for invalid elements within `entries`

, freeing up resources that might be needed to give a mobile user a smooth scrolling experience.

Programmers don’t often write `add()`

functions that often from day to day, so let’s look at a real-world example: applying `.every()`

and `.some()`

to a hypothetical HTML form validation.

We want to submit the form only after all required data have been obtained and validated from the form. We equally want at least one of the optional data to be filled in:

```
const requiredFields = Array.of(
isFirstNameValid(),
isLastNameValid(),
isEmailValid(),
isAboutMeValid()
);
const optionalFields = Array.of(
isTwitterValueValid(),
isFacebookValue(),
isGoogleplusValueValue()
);
const isValid = (inputStatus) => inputStatus === true;
if(requiredFields.every(isValid) && optionalFields.some(isValid)) {
// all required fields are valid
// and at least one social media field is valid
// lets proceed to submit the form now
} else {
// lets tell the user we are serious here
// this will happen really fast since we are short-circuiting
// with .some and .every above
}
```

As seen above, all the functions within `Array.of()`

are doing the validation for specific form fields, and then returning either `true`

or `false`

. Since `Array.of()`

is a factory for constructing arrays from the parameters it is given (the validation functions in our case), this means `optionalFields`

can eventually look like `[true, false, false]`

. This way, if any value in `requiredFields`

is false, or if none of `optionalFields`

is true, we do not submit the form. The form submission is decided with the shortest path of execution.

This exploration helped reveal how prominent **MFR** has become. It also sheds light on why `.every()`

and `.some()`

can give you more efficient strategies for manipulating arrays.

Here are some possible scenarios to promote or adopt .`some()`

or `.every()`

over **MFR** in your Javascript codebase:

- A
`.filter()`

immediately followed by`.forEach()`

,`.map()`

,`.reduce()`

, or any chained combination involving them. - A
`.filter()`

immediately followed by a condition examining the result of the invocation, and where the body of the condition contains a`.forEach()`

,`.map()`

,`.reduce()`

, or any chained combination involving them, acting on the result from the`.filter()`

.

For these and other relevant scenarios, exiting the checks as soon as possible will optimize your resources.

If you’ve enjoyed this tutorial and our broader community, consider checking out our DigitalOcean products which can also help you achieve your development goals.

Leave a comment

This textbox defaults to using **Markdown** to format your answer.

You can type **!ref** in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!