Steven Noble
Steven Noble

Reputation: 10425

Does JavaScript have non-shortcircuiting boolean operators?

In JavaScript

(f1() || f2())

won't execute f2 if f1 returns true which is usually a good thing except for when it isn't. Is there a version of || that doesn't short circuit?

Something like

var or = function(f, g){var a = f(); var b = g(); return a||b;}

Upvotes: 29

Views: 4578

Answers (6)

Erik på kontoret
Erik på kontoret

Reputation: 81

Non-shortcircuiting and: [f1(), f2()].every(i => i)

Non-shortcircuiting or: [f1(), f2()].some(i => i)

To test non-shortcircuiting and in Chrome console, exectute this:

f1 = () => { console.log('evaluating f1'); return false; }
f2 = () => { console.log('evaluating f2'); return false; }
[f1(), f2()].every(i => i)

Result:

evaluating f1
evaluating f2
false

To test non-shortcircuiting or in Chrome console, exectute this:

f1 = () => { console.log('evaluating f1'); return true; }
f2 = () => { console.log('evaluating f2'); return true; }
[f1(), f2()].some(i => i)

Result:

evaluating f1
evaluating f2
true

The square bracket syntax is called array literal. The array is filled with the return values of the functions f1 and f2, which are both evaluated. Then the logic operation is done with each array element as an operand. The logic operations themselves are shortcircuiting, but that does not matter because the operands have already been evaluated. So the construct as a whole is non-shortcircuiting.

Documentation:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#array_literals

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some

Upvotes: 1

0xF
0xF

Reputation: 3708

& and | are bitwise, but if the inputs are booleans, you can often ignore the fact that the result is 0 or 1:

if (f1() | f2())

If you need a boolean result, use "double not" to convert 0 and 1 to false and true respectively:

const orResult = !!(f1() | f2());

If the inputs aren't booleans and you want to be compatible with JavaScript way of treating 0, -0, NaN, undefined, null as false:

const andResult = !!(!!f1() & !!f2());
const orResult = !!(!!f1() | !!f2());

These can be shortened using De Morgan's laws to:

const andResult = !(!f1() | !f2());
const orResult = !(!f1() & !f2());

although the "double not" reads better to me.

Upvotes: 0

Torres
Torres

Reputation: 5400

Nope, JavaScript is not like Java and the only logical operators are the short-circuited

https://developer.mozilla.org/en/JavaScript/Reference/Operators/Logical_Operators

Maybe this could help you:

http://cdmckay.org/blog/2010/09/09/eager-boolean-operators-in-javascript/

| a     | b     | a && b | a * b     | a || b | a + b     |
|-------|-------|--------|-----------|--------|-----------|
| false | false | false  | 0         | false  | 0         |
| false | true  | false  | 0         | true   | 1         |
| true  | false | false  | 0         | true   | 1         |
| true  | true  | true   | 1         | true   | 2         |

| a     | b     | a && b | !!(a * b) | a || b | !!(a + b) |
|-------|-------|--------|-----------|--------|-----------|
| false | false | false  | false     | false  | false     |
| false | true  | false  | false     | true   | true      |
| true  | false | false  | false     | true   | true      |
| true  | true  | true   | true      | true   | true      |

Basically (a && b) is short-circuiting while !!(a + b) is not and they produce the same value.

Upvotes: 14

Eli
Eli

Reputation: 17825

JavaScript DOES have single pipe (|, bitwise OR) and single ampersand operators (&, bitwise AND) that are non-short circuiting, but again they are bitwise, not logical.

http://www.eecs.umich.edu/~bartlett/jsops.html

Upvotes: 2

Paragon
Paragon

Reputation: 2722

If you need f2() to run regardless of whether or not f1() is true or false, you should simply be calling it, returning a boolean variable, and using that in your conditional. That is, use: if (f1() || f2IsTrue)

Otherwise, use single bar or single ampersand as suggested by GregC.

Upvotes: 1

Sean Adkinson
Sean Adkinson

Reputation: 8605

You could use bit-wise OR as long as your functions return boolean values (or would that really matter?):

if (f1() | f2()) {
    //...
}

I played with this here: http://jsfiddle.net/sadkinson/E9eWD/1/

Upvotes: 4

Related Questions