In JavaScript's if-then-else there is technically no elseif branch.
But it works if you write it this way:
if (condition) {
} else if (other_condition) {
} else {
}
To make it obvious what is really happening you can expand the above code using an additional pair of { and }:
if (condition) {
} else {
if (other_condition) {
} else {
}
}
In the first example we're using some implicit JS behavior about {} uses. We can omit these curly braces if there is only one statement inside. Which is the case in this construct, because the inner if-then-else only counts as one statment. The truth is that those are 2 nested if-statements. And not an if-statement with 2 branches, as it may appear on first sight.
This way it resembles the elseif that is present in other languages.
It is a question of style and preference which way you use it.
Answer from Jeff on Stack Overflowif statement - "elseif" syntax in JavaScript - Stack Overflow
conditional operator - Javascript one line If...else...else if statement - Stack Overflow
If else chains Basic JS
From nothing to important actions: agents that act morally — EA Forum
In JavaScript's if-then-else there is technically no elseif branch.
But it works if you write it this way:
if (condition) {
} else if (other_condition) {
} else {
}
To make it obvious what is really happening you can expand the above code using an additional pair of { and }:
if (condition) {
} else {
if (other_condition) {
} else {
}
}
In the first example we're using some implicit JS behavior about {} uses. We can omit these curly braces if there is only one statement inside. Which is the case in this construct, because the inner if-then-else only counts as one statment. The truth is that those are 2 nested if-statements. And not an if-statement with 2 branches, as it may appear on first sight.
This way it resembles the elseif that is present in other languages.
It is a question of style and preference which way you use it.
Just add a space:
if (...) {
} else if (...) {
} else {
}
Sure, you can do nested ternary operators but they are hard to read.
var variable = (condition) ? (true block) : ((condition2) ? (true block2) : (else block2))
tl;dr
Yes, you can... If a then a, else if b then if c then c(b), else b, else null
a ? a : (b ? (c ? c(b) : b) : null)
a
? a
: b
? c
? c(b)
: b
: null
longer version
Ternary operator ?: used as inline if-else is right associative. In short this means that the rightmost ? gets fed first and it takes exactly one closest operand on the left and two, with a :, on the right.
Practically speaking, consider the following statement (same as above):
a ? a : b ? c ? c(b) : b : null
The rightmost ? gets fed first, so find it and its surrounding three arguments and consecutively expand to the left to another ?.
a ? a : b ? c ? c(b) : b : null
^ <---- RTL
1. |1-?-2----:-3|
^ <-
2. |1-?|--2---------|:-3---|
^ <-
3.|1-?-2-:|--3--------------------|
result: a ? a : (b ? (c ? c(b) : b) : null)
This is how computers read it:
- Term
ais read.
Node:a- Nonterminal
?is read.
Node:a ?- Term
ais read.
Node:a ? a- Nonterminal
:is read.
Node:a ? a :- Term
bis read.
Node:a ? a : b- Nonterminal
?is read, triggering the right-associativity rule. Associativity decides:
node:a ? a : (b ?- Term
cis read.
Node:a ? a : (b ? c- Nonterminal
?is read, re-applying the right-associativity rule.
Node:a ? a : (b ? (c ?- Term
c(b)is read.
Node:a ? a : (b ? (c ? c(b)- Nonterminal
:is read.
Node:a ? a : (b ? (c ? c(b) :- Term
bis read.
Node:a ? a : (b ? (c ? c(b) : b- Nonterminal
:is read. The ternary operator?:from previous scope is satisfied and the scope is closed.
Node:a ? a : (b ? (c ? c(b) : b) :- Term
nullis read.
Node:a ? a : (b ? (c ? c(b) : b) : null- No tokens to read. Close remaining open parenthesis.
#Result is:a ? a : (b ? (c ? c(b) : b) : null)
Better readability
The ugly oneliner from above could (and should) be rewritten for readability as:
(Note that the indentation does not implicitly define correct closures as brackets () do.)
a
? a
: b
? c
? c(b)
: b
: null
for example
return a + some_lengthy_variable_name > another_variable
? "yep"
: "nop"
More reading
Mozilla: JavaScript Conditional Operator
Wiki: Operator Associativity
Bonus: Logical operators
var a = 0 // 1
var b = 20
var c = null // x=> {console.log('b is', x); return true} // return true here!
a
&& a
|| b
&& c
&& c(b) // if this returns false, || b is processed
|| b
|| null
Using logical operators as in this example is ugly and wrong, but this is where they shine...
"Null coalescence"
This approach comes with subtle limitations as explained in the link below. For proper solution, see Nullish coalescing in Bonus2.
function f(mayBeNullOrFalsy) {
var cantBeNull = mayBeNullOrFalsy || 42 // "default" value
var alsoCantBe = mayBeNullOrFalsy ? mayBeNullOrFalsy : 42 // ugly...
..
}
Short-circuit evaluation
false && (anything) // is short-circuit evaluated to false.
true || (anything) // is short-circuit evaluated to true.
Logical operators
Null coalescence
Short-circuit evaluation
Bonus2: new in JS
Proper "Nullish coalescing"
developer.mozilla.org~Nullish_coalescing_operator
function f(mayBeNullOrUndefined, another) {
var cantBeNullOrUndefined = mayBeNullOrUndefined ?? 42
another ??= 37 // nullish coalescing self-assignment
another = another ?? 37 // same effect
..
}
Optional chaining
Stage 4 finished proposal https://github.com/tc39/proposal-optional-chaining https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
// before
var street = user.address && user.address.street
// after
var street = user.address?.street
// combined with Nullish coalescing
// before
var street = user.address
? user.address.street
: "N/A"
// after
var street = user.address?.street ?? "N/A"
// arrays
obj.someArray?.[index]
// functions
obj.someMethod?.(args)