Why does JavaScript's logical AND (&&) not work the same as an if conditional?

Viewed 129

I've been doing JS development for a long time now, and for years I thought I could short circuit a conditional statement using the logical AND. In fact, I do this ALL THE TIME in my React components with conditional rendering. But it turns out it doesn't work the way I would expect all the time. The question is, why?

Here is an example for Node 8.15.0:

> a = 0.0
0
> a && console.log(a)
0
> if(a) console.log(a)
undefined
> !!a && console.log(a)
false

Specifically, why does a && console.log(a) not work the same as if (a) console.log(a)

3 Answers

if(a) ... is a statement. a && ... is an expression.

This behaviour is specific to a console. If a line evaluates to an expression, the result outputted, otherwise it's considered that a line was evaluated to undefined.

a && ... is a short-circuit. This means that if a is falsy, the expression evaluates to a. If a is truthy, the expression is evaluated to ....

This doesn't affect the way both are used in real application instead of a console. If the result of the evaluation isn't used, both if and short-circuit evalution act the same way, i.e. evaluate ... only if a condition is truthy.

!! operator convert variable to boolean. In your case a equal to 0 so it will convert it to false, and because of this you see false as output for !!a && console.log(a)

The first expression outputs 1 line to the console, which is what the statement evaluates to:

a && console.log(a)
0

The expression clearly evaluates to the value of a. That's because this short circuit evaluation can be considered equivalent to the following conditional ternary:

a ? console.log(a) : a

The second expression evaluates to undefined because it is not an actual expression but a block construct. With braces this time:

if (a) { console.log(a) }
undefined

The third expression is quite similar to the first one, except that this time not the value of a is returned but the value of the sub-expression !!a, or false:

!!a && console.log(a)
false

Note If a would be a truthy value both the first and third statements would evaluate to undefined, the return value of console.log.

Related