Reputation: 2101
I have a variable 'fieldCount' that is equal to 5 (the number of fields I have). How can I write the following out without specifically stating each index:
if (
fields[0].checkValidity() && fields[1].checkValidity() && fields[2].checkValidity()
&& fields[3].checkValidity() && fields[4].checkValidity()
) {
fieldsPass = true;
}
Upvotes: 3
Views: 11153
Reputation: 191976
You have an array of fields, and you want to iterate them, and invoke a validity check method on each of them. Only if all of them pass, the flag fieldsPass
would be true
.
This is exactly the behavior of Array#every
. According to MDN:
The every() method tests whether all elements in the array pass the test implemented by the provided function.
Use Array.every
to invoke checkValidity()
on each field. If all fields are valid, the result would be true
. If one field fails checkValidity()
, the loop would return false
immediately, without checking the other fields.
var fieldPass = fields.every(function(field) {
return field.checkValidity();
})
Upvotes: 3
Reputation: 50241
You can use a loop, or some fairly standard built-in browser functions.
Here's how to do it with a loop. This should be the fastest code, but you probably don't need the fastest code unless you are checking a huge number of fields on a huge number of items. I recommend instead the "correct, clear, concise, fast" priorities, so think you should start with the built-in browser functions. But here it is for reference:
var fieldsPass = true;
var i, l = fields.length;
for (i = 0; i < l; i += 1) {
if (fields[i].checkValidity()) continue;
fieldsPass = false;
break;
}
Note that declaring the i
variable outside of the loop and capturing the field length outside the loop are optional.
The first I did because many people don't know about hoisting, and the fact that for (var i ...
does NOT create a variable only available inside the for
loop, it is the same as having declared var i
at the top of the function, and this behavior can lead to bugs.
The second I did out of habit, though as I said you can put it inside the loop check. See this discussion. If you do use the loop method, you're probably looking for better performance, so might want to use the captured length way for the best possible performance. (And if it really matters that much, you can do the var i = fields.length; while (i--) { }
method.)
You can use Array.prototype.every() (from ECMAScript 2015 6th edition):
The every() method tests whether all elements in the array pass the test implemented by the provided function.
fieldsPass = fields.every(function(field) {
return field.checkValidity();
});
It returns true
when the passed-in function, when run on every item in the array, returns true
for all of them. If any one returns false
, it stops and returns false
. In some languages, they call the same concept all, if you're familiar with that.
Alternately, it might be better to declare your checkValidity
function once, instead of putting it on every field. This may not be possible, depending on how you implemented it (perhaps it has access to private variables?). Notice that the first argument of the callback function you provide (see the documentation in the links above) is the currentValue
of the iteration, the field you want to check. If your function thus looks like this, it will work:
function checkValidity(field) { /* check validity */ }
fieldsPass = fields.every(checkValidity);
You can use also Array.prototype.some() (from ECMAScript 2015 6th edition):
The some() method tests whether some element in the array passes the test implemented by the provided function.
fieldsPass = !fields.some(function(field) {
return !field.checkValidity();
});
Notice that it is basically just the inverse of every
, as "ALL VALID" is the same as "NOT (ANY INVALID)". It just means that it checks for any one item in the array that passes the function, and if so, returns true
. In some languages, they call the same concept any, if you're familiar with that.
Note that for these two functions, browser compatibility is pretty good. If you don't care about IE below version 9 then you're pretty much safe. If you do, then you would want to use a polyfill, which is available on the above-linked MDN pages. You would include that code in the global scope of your javascript file, and then would be able to use it as normally in IE 8 and below. (I'm talking about the code block starting like this:)
if (!Array.prototype.every) {
Array.prototype.every = function(callbackfn, thisArg) {
...
}
Upvotes: 4
Reputation: 896
You can do it like this:
fieldsPass = true;
for (i = 0; i < fieldCount; i++)
{
if(!fields[i].checkValidity())
{
fieldsPass = false;
break;
}
}
Upvotes: 1
Reputation: 11116
You can use the .some()
method and reverse the logic to tell if all passed like so:
var allPassed = !fields.some(function (field) {
return !field.checkValidity();
});
Upvotes: 1
Reputation: 32511
Like you said, use a loop.
var fieldsPass = true;
for (var i = 0; i < fields.length; i++) {
// Exit early if one of them fails
if (!fields[i].checkValidity()) {
fieldsPass = false;
break;
}
}
Upvotes: 2