8

I need to execute both sides of an && statement, but this won't happen if the first part returns false. Example:

function doSomething(x) {
    console.log(x);
}

function checkSomething(x) {
    var not1 = x !== 1;
    if (not1) doSomething(x);

    return not1;
}

function checkAll() {
    return checkSomething(1)
        && checkSomething(3)
        && checkSomething(6)
}

var allValid = checkAll(); // Logs nothing, returns false

The problem here is that doSomething(x) should log 3 and 6, but because checkSomething(1) returns false, the other checks won't be called. What is the easiest way to run all the checks and return the result?

I know I could save all the values in variables and check those subsequently, but that does not look very clean when I have a lot of checks. I am looking for alternatives.

20
  • 5
    I know I could save all the values in variables and check those subsequently You already know the answer, unfortunately it's not very pretty as you state. Commented Jan 30, 2016 at 11:02
  • 2
    Why do you need to know the result of all the checks? Doesn’t the return statement imply that you want to know whether all checks return true? Then you also don’t need to evaluate all the checks… If you want to get the result of each check individually, then use the suggestion with the array literal from A.Wolff. Commented Jan 30, 2016 at 11:07
  • 3
    Your checkSomething handles two separate tasks at the same time which is generally bad practice and leads to problems like this. Depending on what the actual use case is, if doSomething has to run twice you should do that task separately instead of relying on it being a consistent side effect of checkSomething. Commented Jan 30, 2016 at 11:09
  • 1
    The point of short circuiting is that once the outcome of the logic expression is known, the following parts of the expression will not change the outcome so why run them. Is that not the case for you? So, once you find a false value, the overall result of three && operations can never be true so why execute them? Unless you have side effects in those parts of the expression (which is an evil way to code). Fix your code rather than code this way. Commented Jan 30, 2016 at 11:09
  • 1
    No, it would definitely solve this problem. You don't need a variable for each return value, you need only one flag that checks if at least one of them has returned false. Commented Jan 30, 2016 at 11:17

3 Answers 3

11

Use a single &. That is a bitwise operator. It will execute all conditions and then return a bitwise sum of the results.

 function checkAll() {
    return checkSomething(1)
      & checkSomething(2)
      & checkSomething(3)
 }
Sign up to request clarification or add additional context in comments.

4 Comments

This will return 1 or 0, not true or false, but it seems like a productive direction.
return !!(checkSomething(1) & checkSomething(2) & checkSomething(3)) to get boolean
better return !!(checkSomething(1) | checkSomething(2) | checkSomething(3))
That’s OR, @Thomas.
7

You can multiply the comparison result and cast it to boolean.

function checkSomething(x) {
    var not1 = x !== 1;
    if (not1) alert(x);
    return not1;
}

function checkAll() {
    return !!(checkSomething(1) * checkSomething(2) * checkSomething(3));
}

document.write(checkAll());

Or take some array method:

function checkAll() {
    return [checkSomething(2), checkSomething(2), checkSomething(3)].every(Boolean);
}

3 Comments

Why would you multiply when you could use the & operator? That way it would still read as "something AND something AND something"...
then use a bitwise or |
The array method worked best for me, TypeScript did not seem to like the others
0

Coming back to my own question 2,5 years later I can agree with the people in the comments on how bad this code is by being based on side effects and therefore violating the single responsibility principle.

I just want to provide a proper solution for people visiting this page with the same question.

function doSomething(x) {
    console.log(x);
}

function checkSomething(x) {
    return x !== 1;
}

var values = [1, 3, 6];
var validValues = values.filter(checkSomething); // -> [3, 6]

validValues.forEach(doSomething); // -> Logs 3 and 6
var allValid = validValues.length === values.length; // false

As you can see, the checkSomething function now only does one thing: check something. The doSomething logic runs separately after all the checks are done.

A function should always either do something or return something, not both. Of course there are exceptions to this, but it is a good rule of thumb. This makes the code more predictable, testable and understandable.

Now, if at some point I want to check if all values are valid without "doing something", I can actually do this...

var allValid = checkSomething(1) && checkSomething(3) && checkSomething(6);

...without having to worry about side effects.

Conclusion: You don't want to avoid short circuited evaluation

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.