As others (@conor-mancone, @jasoninvegas) have pointed out, the code is having bigger problems than purely syntax related ones...
- There're too many things this little piece of code is looking at once.
- It's written in a very low level, instead of abstracting things out. (I.e. why should I bother with
code === 0 ...especially in the same line where stage and isEditable are used? Are those even related concepts of the same level of abstraction?) 0 and 2 codes may be familiar to you, but to a regular users they are "magic numbers".
You may not be ready or want to jump into @jasoninvegas' state machine proposal, but you should consider it among the alternatives you have. As the very first step, I'd recommend looking at plain old extract method refactoring...
Syntax-wise I only can suggest a little improvement if you have a luxury of ES6.
Screw the old school endless if-else if-else if-else chains. They don't allow immediate assignment to the target variable/constant. In fact, that construction enforces using var or let instead of a const (which helps avoiding bugs).
- Extract the
if conditions into tiny predicate arrow functions. - Use those arrow functions in a ternaries chain. This will allow you to have a united
const declaration together with an immediate assignment.
Oh, and by the way, use === consistently. Not sure why in some places you use == instead...
const isNotAString = response => typeof response !== 'string'; const isCompleted = status => status.indexOf('Completed') !== -1; const isEditableAndInEditMode = (stage, isEditable, code) => (stage <= isEditable) && (code === 0 || code === 2); // Make `0` and `2` named constants! const mode = isNotAString(response) ? edit : isCompleted(status) ? display : isEditableAndInEditMode(stage, isEditable, code) ? edit : display;
Update 1, for those who are unfamiliar with functional programming. If ternary chaining was that bad, it wouldn't be mentioned Mozilla Developer Network
By breaking the ternary onto multiple lines and making use of extra whitespace, the ternary operator can be used to very cleanly replace a lengthy series of if/else statements. This provides a syntactically light way of expressing the same logic:
var func1 = function( .. ) { if (condition1) { return value1 } else if (condition2) { return value2 } else if (condition3) { return value3 } else { return value4 } } var func2 = function( .. ) { return condition1 ? value1 : condition2 ? value2 : condition3 ? value3 : value4 }
Update 2 A related blog post. and a comment on it, and another one tell more about ternaries in functional programming.
Another way to look at it is through the prism of a truly FP language, such as Haskell. Here's a link to comparison of if-vs-pattern-matching. In fact, a chain of ternaries resembles pattern matching functionality a lot (yet, not necessarily the same).
Do not stick to the old dogma of "ternary is bad"! Harness it for the win!