JavaScript gotchas - not all your conditions are booleans
Tags: javascript, webdev, beginners, coding
Published: 2023-11-20 07:44:25

One thing I like about JavaScript is its shothand evaluation whether a variable contains a value. Instead of the tedious `if (text !== undefined && text !== null && text.length > 0)` comparison we can just write `if (text)` and it works the same.

You just need to be careful if you want to use more such conditions. When you type:

```js
let text1 = 'text1'
let text2 = 'text2'
console.log(text1 && text2)
console.log(text1 || text2)
```

you won't get `true`, as inattentive JS devs tend to expect from time to time, but `'text2'` from the first and `'text1'` from the second log. Huh? :dizzy_face:

The [_truthiness_](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) of variable `text1` is still being evaluated first. Therefore, the program advances to `text2`, but after the evaluation is finished, JavaScript is left with the real value of the string, and so it returns it. The unsuspicious machine doesn't expect you didn't feed it `boolean` values as you properly should. In the later case with "or", `text1` is _truthy_, so it satisfies the condition and the actual value of the variable is dropped from the expression. The simple `if (text)` in fact does exactly the same. But since we don't work with the returned value any futher as we just wanted to know if _**something**_ is there, we don't even notice and it works for us. But not anymore with two or more variables.

Similar shenanigans are probably the reason why many programmers gained feeling that JavaScript is all but an evil and mess that should be avoided at all costs. While it is rather their fault when they try to cram illogical combinations into it. _**“Play stupid games, win stupid prizes.”**_.

I originally thought I'd go in deeper deatail about the rules for evaluating operators in JavaScript, but it's actually a bit complicated with all the edge cases, so here's just a link to the documentation for [`&&`](https://developer.mozilla.org/en-US/docs/Web/ JavaScript/Reference/Operators/Logical_AND) and [`||`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_OR) for those who are interested (there are also other logical operators).

In order to make logical operations work really logically, we need to feed them operands that are actual `boolean`, i.e. `true` or `false` by themselves, and not thanks to some background magic. Otherwise, sooner or later you will find yourself debugging the application in disbelief and wondering why the condition isn't evaluated as you expected.

If you're worried that this means going back to a "chatty" explicit comparison with several possible (non)values, do not despair. We have a trick for that. Simply rewrite it as:

```js
console.log(!!text1 && !!text2)
console.log(!!text1 || !!text2)
```

It works! But why? :eyes:

Don't worry, I had a "WTF?" moment when I first saw this too. But there is nothing magical about double negation. Again, the JavaScript starts by evaluating the _truthiness_ of the `text1` variable, and since `'text1`' is there, it has the value of `true` internally. Now we negate it with the first `!` and then we negate with the second `!` again. Maybe you remember from mathematics - _**"The product of two negatives is a positive"**_.

If it were the other way around and `text1` was `undefined`, `null` or an empty string, JavaScript would first say `false`, the first negation would make `true` and the second would finally return `false`.

Using the concatenation of two logical NOTs `!!`, we get a simple, universal and always functional conversion of JavaScript values into `boolean` expressions, which can then be safely used and chained for logical evaluation of conditions. Keep this in mind when writing your JS code and be prepared to look for incorrect usages if you seek for bugs in existing programs.

Have you ever encountered this in your code or codes you had to debug? Share your experience in the comments!