lodash every collection method and vanilla js alternative

The lodash every collection method can be used to test if each key value in a collection meets a condition that is defined in the body of a function that is passed as one of the arguments. So it can for example be used to test if all elements in an array are a number, if all elements in an array are objects of a certain constructor, and so forth.

In native javaScript there is the array every prototype method, and it would seem that this native method has decent browser support. It is an array method rather than a collection method as is the case with lodash every, but will work just as well when it comes to arrays.

In this post I will be quickly going over the lodash every method as well as the native Array.every method and other native javaScript ways of testing if all values in an object will satisfy a given condition.

1 - lodash every Basic example

So I often start of a post by quickly getting into a basic example of what it is that I am writing about in the post. So for this post on the lodash every method here is a simple example where I just have two arrays. One of which is all numbers, and the other of which contains one string.

I then have a function that can be used with the lodash _.every method that will return true of a given element in an array or key name in an object is a number. When I call the lodash every method I pass an array as the first argument and give the method that checks for a number as the second argument.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let _ = require('lodash');
// two arrays one has nothing but numbers
// the other has a single element that is
// a string.
let arr1 = [1, 2, 3, 4],
arr2 = [1, 2, 'c', 4],
// a method that can be used to test
// if all elements are a number
tester = (el) => {
return typeof el === 'number';
};
// using the tester method with _.every
console.log(_.every(arr1, tester)); // true
console.log(_.every(arr2, tester)); // false

2 - The _.every method can be used on plain old objects

So because the lodash every method is a collection method that means that it can be used on plain old objects that are a collection of sorts. Say I have an object with a bunch of public keys, and I want to make sure that each key meets a certain set of criteria. For example I want each property to be an object, and I want each of those objects to have a property of a certain name, and for that property to be of a specific type and value. There are many ways of going about doing that, but if lodash is there it can be quickly done with the lodash every method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
let _ = require('lodash');
// a plan old object that is
// a collection of sorts
let items = {
apple: {
cost: 2
},
raspberry: {
cost: 5
},
blackberry: {
cost: 4
}
};
// a method to check each key in the object
let hasCost = function (item) {
// is item an object?
if (typeof item === 'object') {
// false if null
if (item === null) {
return false;
}
// Some rules for a cost property
if (typeof item.cost === 'number' && item.cost >= 0) {
return true;
}
}
// if we get here yeah false
return false;
};
// Evey can be used to check that every item
// meets the given set of conditions
console.log(_.every(items, hasCost)); // true
items.newProduct = null;
console.log(_.every(items, hasCost)); // false

3 - Vanilla js alternatives to lodash every

So now that we know the basic deal about that lodash every method, maybe we should now look at some plain old vanilla javaScript alternatives to using the lodash every method. After all there is now a native Array.every method that can be used to replace it, and this can be chalked up as yet another reason as to not bother with lodash anymore right? Well yes and no, lets look at the reasons why, and also some additional ways of going about checking all keys in an object for some kind of condition.

3.1 - Of course array every will work with arrays

So there is the native array every method that will of course work just fine with arrays.

1
2
3
4
5
6
7
8
let arr1 = [1, 2, 3, 4],
arr2 = [1, 2, 'c', 4],
tester = (el) => {
return typeof el === 'number';
};
// using the tester method with every
console.log(arr1.every(tester)); // true
console.log(arr2.every(tester)); // false

There is however the question of array like objects, named key objects, and other ways of doing something like this that will work in really old browsers. So with that said lets look at some more examples of how to do what the lodash every method does with just native javaScript by itself.

3.2 - The Array.every method will work okay with array like objects with Function.call

So the native Array.every method will work just fine in most cases, assuming that all the clients that you want to support have it for starters. Also assuming that you will always want to use the Array.every method with well Arrays, in the event that you are dealing with a collection that is an object you will not be able to use it and get expected results. At least not with the array every method by itself anyway.

Sometimes you might be dealing with an Array like object that is formated like an Array, in other words it is an object with a length property, and numbered key names. When it comes to these kinds of objects the array every method will work okay with the use of the Function.call prototype method.

1
2
3
4
5
6
7
8
9
10
11
12
13
let arrLike = {
0 : 7,
1 : 8,
2 : 'nope',
length: 3
},
tester = (el) => {
return typeof el === 'number';
};
console.log([].every.call(arrLike, tester)); // false
arrLike[2] = 9;
console.log([].every.call(arrLike, tester)); // true

This is typically of course of many of the native Array methods, they will work okay in most situations. However because they are very much array methods rather than collection methods they will not work in some situations involving plain old objects that are being used as a kind of named array.

3.3 - I can get array every to work okay with named keys in plain old objects by pulling Object.values into the mix

So the every method works just find with arrays, it can also be used with array like objects by making use of the function call prototype method. However what about collection objects that have no length property, and even if it did it would not help because the object has named rather than numbered public keys? The lodash every method will just work with them out of the gate, sure. However it is not all that hard to get array every to work with just plain old objects like this to by just using the Object.values static Object method to create an array of values from an object like this, then the array every method can be used with that as we are now dealing with an array.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let items = {
apple: {cost: 2},
raspberry: {cost: 5},
blackberry: {cost: 4}
};
let hasCost = (item) => {
if (typeof item === 'object') {
if (item === null) {return false;}
if (typeof item.cost === 'number' && item.cost >= 0) {
return true;
}
}
return false;
};
// does not seem to work as expected with my items
// object
console.log([].every.call(items, hasCost)); // true
items.fooberry = null;
console.log([].every.call(items, hasCost)); // true

3.4 - Making my own every method with Object.values

So then there is the idea of making my own vanilla js version of the lodash every method. Doing so is not to hard and there are a wide range of ways that I can think of to go about doing it involving loops and other native methods. I will not be going through the process of finding every which way to do this of course, but for this example I will be using the Object.values static Object method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// An every method could be written like this
// with Object.values
let every = (obj, forEach) => {
let i = 0,
values = Object.values(obj),
len = values.length;
while (i < len) {
if (!forEach(values[i])) {
return false;
}
i += 1;
}
return true;
};
// lets put it to the test
let arr1 = [1, 2, 3, 4],
arr2 = [1, 2, 'c', 4],
obj1 = {
foo: 5,
bar: 7
},
obj2 = {
foo: 'string',
bar: null
},
tester = (el) => {
return typeof el === 'number';
};
// works as exspected
console.log( every(arr1, tester) ); // true
console.log( every(arr2, tester) ); // false
console.log( every(obj1, tester) ); // true
console.log( every(obj2, tester) ); // false

So the nice thing about this is that it works just like the lodash every method in the sense that it works okay with arrays, and objects in general. Even if they are not formated like and array, and are thus array like objects. Most browsers support the Object.values method okay, but this example might still break on some older clients, so lets see about another example.

3.5 - Using a for in loop

A for in loop could be used to make an every method that will work on a wide range of clients. Not that doing so matter a whole lot these days unless for some reason you are getting a whole lot of traffic from people that are using very old browsers for some reason.

1
2
3
4
5
6
7
8
var every = function (obj, forEach) {
for (var prop in obj) {
if (!forEach(obj[prop])) {
return false;
}
}
return true;
};

4 - Conclusion

The lodash every method is a collection method that can be used to check if all the elements of an array, or all the ublic key values of an object in general meet a given condition. There is also the native array every method that will do the same only with just arrays, and array like object when used with the function call prototype method.