loading...

Javascript ||, aka Why Doesn't This Work?!

laurieontech profile image Laurie Originally published at laurieontech.com ・2 min read

There is a piece of JavaScript syntax I, and others, seem to always want to work and it doesn't.

const isThisOrThat = "that" === ("this" || "that")
// this is false

Why doesn't this work? Let's talk about it!

Inside the parens

If we go by order of operations, the inside expression evaluates first.

What does "this" || "that" mean in JavaScript?

I'll be honest, this one breaks my math brain a bit. In math, a || b = b || a. The or operator is commutative, so order doesn't matter. That's not true in JavaScript, order matters a lot.

Let's look at two examples.

const example = "" || "that"
// "that"

The first thing JavaScript does is check for the "existence" of the first value. JavaScript is checking for a falsey value, empty string is falsey. Since the first value doesn't exist, it returns the second value.

This happens even if the second value is also falsey.

const example = "" || ""
// ""

So what happens if the first value is truthy, as in our original example?

const example = "this" || "that"
// "this"

example evaluates to "this".

Equality check

Now we start to realize why our expression up top doesn't work. We can break it into two pieces.

const example = "this" || "that"
const isThisOrThat = "that" === example
// false

At the time that we're checking equality, the string "that" is nowhere to be found.

What makes this strange is that order matters.

const example = "that" || "this"
const isThisOrThat = "that" === example
// true

Flipping the original or expression changes the resulting equality check.

Making sure this works

If we truly want to check both strings, we need to check equality twice.

const isThisOrThat = "that" === "this" || "that" === "that"
// true

Alternatively, we can use an array check. This one feels a bit more natural.

const isThisOrThat = ["that", "this"].includes("that")
// true

Or is weird

People use or a lot to flip values or set defaults, etc. It's never been my favorite because of examples like the ones above. Once you start composing that expression it can confuse the issue.

Discussion

pic
Editor guide
Collapse
z00md profile image
z00md

Yeah, at first it can be confusing. Just one more point to add - In case of Logical OR || it behaves as a short circuit. So if you use expressions and your first expression becomes truthy, other expressions will never be evaluated. If there is a function call, it will not execute.

// if isUserMember() returns truthy value, isUserAuthorised() will never be called
var result = isUserMember(userdetails) || isUserAuthorized(userdetails);
Collapse
laurieontech profile image
Laurie Author

Absolutely

Collapse
harithay profile image
harithay

I agree that this is a very confusing point that result in really bad code. TypeScript is in a quest to fix issues such as this. I don't think JavaScript || breaks any math logic. It is still commutative. Problem is that we sees "this" and "that" as two string, but for the || operator, they are both just two boolean 'true's. Your equation, a || b = b || a, turns in to true || true = true || true when both a and b is a string. When evaluating this logic with || operator, it doesn't matter which true value sends to the user so to be fast JS (or any other sane language) returns the first result. To avoid confusion, you could always use !! to get the boolean value before do the ||. i.e !!a || !!b

Collapse
laurieontech profile image
Laurie Author

Ah, but it doesn't return a boolean. It returns the value. So yes, the operation logic is reasonable, but the return structure breaks the concept. It's no longer commutative at that point.

Collapse
manchicken profile image
Michael D. Stemle, Jr.

Yeah, stuff like this can be counter-intuitive. The nice thing is that once you learn this in a language like JavaScript, you now understand it in a number of other languages as well.

Thanks for the write-up!

Collapse
lexlohr profile image
Alex Lohr

There are two finer points of the language that may be confusing sometimes even to experienced developers.

The first one is type coercion, which is an automatism to align values for the task at hand. For example, a logical operator will coerce any value to a boolean for the sake of evaluation. An empty string is falsy, a string containing characters isn't. There's quite a complex set of rules to this, and it makes the language easily confusing.

That brings us to the second one, which is operator precedence. I'll spare you the details, it's just that some operators are processed prior to other ones.

Especially in combination, these two points lend themselves to a many WTF-moments when writing JavaScript.

Collapse
laurieontech profile image
Laurie Author

No question. And that’s the former is what most of this post focuses on. It resolves each side of the operator to a Boolean and operates accordingly.

Collapse
puf17640 profile image
Julian Pufler

As someone who learnt coding through school (5 years at a higher technical school) this is something I don't even consider confusing because of how conditionals were taught to me, it never really was something I was facing because we started out with Java and C# and such logic wouldn't have worked. So when I started coding in Javascript alot of stuff that I see people learning it by themselves are struggling with were already clear for me.

Appreciate the effort though, very interesting write up! Keep it up!

Collapse
functional_js profile image
Functional Javascript

Great js quirk analysis Laurie.

Thanks to eslint, this would never get checked in.

yoda coding

As Yoda would say....
Confuzzled, I made you;
Amuse me, this does.

:)

Collapse
abbadev profile image
Abdulla T

Nice post.