JordanBarber
JordanBarber

Reputation: 2101

Looping through array in if statement to check if all values pass

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

Answers (5)

Ori Drori
Ori Drori

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

ErikE
ErikE

Reputation: 50241

You can use a loop, or some fairly standard built-in browser functions.

Loop

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.)

Browser Function Array.Every

You can use Array.prototype.every() (from ECMAScript 2015 6th edition):

Mozilla Developer Network

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 truewhen 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);

Browser Function Array.Some

You can use also Array.prototype.some() (from ECMAScript 2015 6th edition):

Mozilla Developer Network

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.

General Browser Compatibility Notes

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

Boby
Boby

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

mhodges
mhodges

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

Mike Cluck
Mike Cluck

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

Related Questions