14

So, a junior programmer on my team today wrote the following piece of code:

if(status === ("incomplete" || "unknown"))

Which is obviously not going to do what he intended, which was this:

if(status === "incomplete" || status === "unknown"))

But what I can't explain is why exactly the first snippet of code wouldn't work! Or why it evaluates to true if 'status' is set to 'incomplete' but to false when it's set to 'unknown'...

moloko
  • 423
  • 4
  • 8

3 Answers3

21

In JavaScript, the || operator returns its first operand if it evaluates to true (i.e. it is not false, null, undefined, "", or 0), and its second operand otherwise.

In the first case, ("incomplete" || "unknown") always evaluates to "incomplete", since it evaluates to true.

The entire condition then becomes:

if (status === "incomplete")

Which explains the behaviour you are observing.

Brad
  • 159,648
  • 54
  • 349
  • 530
Jeremy Roman
  • 16,137
  • 1
  • 43
  • 44
  • +1 - you were 9 seconds faster with a fully formed answer. Wow. – insertusernamehere Mar 11 '13 at 16:26
  • 2
    "...returns its first operand if it evaluates to `true`..." I'd change it to say "returns its first operand if it's truthy", your parenthetical basically explains this, but "truthy" and "falsey" are the words most commonly used to express this concept. – zzzzBov Mar 11 '13 at 16:47
  • I normally do use the words "truthy" and "falsey", though I've found that they usually confuse newcomers. But yes, that is precisely what I mean. – Jeremy Roman Mar 11 '13 at 22:34
  • @zzzzBov It's a bit more complicated than that, for example "0" is "truthy" but "0"==false . JavaScript "falsiness" is tricky. I absolutely agree that some comment about not relying on || for when expecting tricky values are expected. – Benjamin Gruenbaum Mar 13 '13 at 08:29
  • @BenjaminGruenbaum, truthiness is not about a comparison against `true` or `false`, it's whether or not it evaluates as true in an if statement. Most of the time, logical comparisons in JavaScript should be done using the strict comparison operator (`===`). For example, `null`, and `undefined` are both falsey, and they both fail when compared to `false` (i.e. `null == false` is `false`). – zzzzBov Mar 13 '13 at 13:09
  • I know that -_-, (The example in my comment is just such a distinction) I just thought it should be mentioned in the answer. – Benjamin Gruenbaum Mar 13 '13 at 13:14
6

("incomplete" || "unknown") will return "incomplete" which is than compared to status.

insertusernamehere
  • 23,204
  • 9
  • 87
  • 126
3

But what I can't explain is why exactly status === ("incomplete" || "unknown") wouldn't work

That's because the expression in the parenthesis is evaluated first. The non-empty string incomplete is truthy, so the OR-expression ("incomplete" || "unknown") yields "incomplete" and only that is then compared with your status variable.

To shorten the condition, there are many ways including arrays of values, regular expression test etc.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375