Inline if statements, also referred to as conditional or ternary operators, allow for compact inline conditional logic in JavaScript. We will cover basics and best practices around usage.
Introducing Inline Ifs
The ternary operator syntax lets you evaluate a condition followed by an expression to execute if truthy, and another if falsy:
condition ? expressionIfTrue : expressionIfFalse
For example:
let accessAllowed = (age > 18) ? true : false;
Here if the age is over 18, access is allowed. Otherwise access is denied.
This conditional assignment is equivalent to:
let accessAllowed;
if (age > 18) {
accessAllowed = true;
} else {
accessAllowed = false;
}
But as you can see, inline ifs let you achieve the same conditional logic in a single line.
Use Cases
Common use cases where ternary operators shine:
- Conditional rendering: Showing/hiding elements based on state
- Toggling visibility: Setting element visibility based on some condition
- Validation: Checking form input before submission
- Default values: Assigning defaults based on existence of variables
- State mapping: Translating logical conditions to enum values
- Short circuiting: Early return if condition unmatched
Later we‘ll see examples of these in action.
Syntax Fundamentals
Let‘s break down the syntactic elements:
- The condition can be any expression that evaluates to true or false.
- The ? separates the condition from the true expression.
- The : delineates between the true and false expressions.
- Both expression1 and expression2 are required and can be any valid values or code blocks. Their types don‘t need to match.
Expressiveness-wise ternary operators have the same capabilities as multiline if statements!
Truthy Falsy Caveat
One key difference is ternary operators check for strict true or false unlike if statements. For example:
let value = 0;
let result = value ? ‘truthy‘ : ‘falsy‘; // falsy
if(value) {
result = ‘truthy‘;
} else {
result = ‘falsy‘;
}
Here value 0 is falsy. The ternary operator assigns ‘falsy’ correctly. The multiline if statement however assigns ‘truthy‘ since 0 is still a valid value.
So remember, ternaries check for strict true/false whereas if statements rely on truthy/falsy coercion.
Pattern Matching
A common pattern is using ternary chains to match different condition scenarios:
function getFee(accountType) {
return (accountType === ‘NORMAL‘) ? 2
: (accountType === ‘SILVER‘) ? 5
: (accountType === ‘GOLD‘) ? 7 : 0;
}
Here the function checks accountType to return an associated fee amount. The last 0 acts as a default else value.
Compare to Switch Case
The above pattern can also be implemented using a switch case statement:
function getFee(accountType) {
switch(accountType) {
case ‘NORMAL‘: return 2;
case ‘SILVER‘: return 5;
case ‘GOLD‘: return 7;
default: return 0;
}
}
So when is each option preferable?
- Ternary: Better for binary yes/no logic and boolean checks
- Switch: Handles complex match scenarios with cleaner multi-way branching
As always, strive for readability first. Ternary chains often tend to go complex quickly.
Nested Conditions
An advantage of inline ifs is the ability to nest condition chains:
let message = (loginCount > 0) ?
(loginCount > 10) ? ‘Power User‘ : ‘Regular‘
: ‘Anonymous‘;
Here if loginCount exceeds 10, we set the message to ‘Power User’, otherwise ‘Regular’ if count > 0. If not, the default is ‘Anonymous’.
Nested Logic Flow
Visually, the logic flow looks as:
This demonstrates how we can model complex decisions concisely.
But beware deeply nested ternaries are harder to comprehend at a glance.
Flattening Conditionals
An alternate way to write the above using separate inline ifs:
let status = loginCount > 0;
let type = status ? (loginCount > 10 ? ‘Power’ : ‘Regular’) : ‘Anonymous’;
let message = type + ‘ User’;
The key thing is flattening conditional blocks into separate expressive statements.
So for complex logic, flatten into stages for enhanced readability.
Nullish Coalescing Operator
JavaScript also introduces the ?? nullish coalescing operator as shorthand for null/undefined checks:
let username = user?.name ?? ‘Anonymous‘;
If user.name exists, use it. Otherwise default to string ‘Anonymous‘.
We can augment with ternary operators:
const messages = count > 0 ? messages : [];
const lastMessage = messages?.[0] ?? ‘No messages‘;
Here we default to empty array if messages undefined before safely accessing first element.
Boolean Logic Short Circuiting
For boolean logic, ternaries allow for short-circuiting engine evaluation for early return scenarios:
function checkPermission(role, enabled) {
return (role === ‘admin‘ || enabled) ? true : false;
}
Here if role matches admin, we skip even checking enabled. The engine short circuits after the OR condition is satisfied rather than evaluate both, improving performance.
Measuring Performance
Let‘s examine some metrics demonstrating performance for different conditional techniques.
Construct | Ops / sec | Relative margin |
---|---|---|
If Statement | 95,891 | 1x slower |
Ternary Operator | 96,362 | 1.0047x faster |
Switch Statement | 92,285 | 1.0386x slower |
Source: jsben.ch Performance Benchmarks
We can draw some inferences:
- Ternary edges out If Statements slightly in operations per second
- Switch performs worse likely due to increased function overhead
So ternaries have a slight performance advantage, but readability and matching tools to the use case is much more important. Optimize for people before computers!
GitHub Usage Trends
Analyzing the GitHub language corpus offers useful insights into usage prevalence:
We see ternary usage relatively stable, hovering between 30%-35% of if statement volume. So ternaries enjoy consistent adoption for their conciseness.
There is a slump around 2018 likely due to the increase in tools auto-converting ternaries to if statements. But usage rebounds as developers recognize their utility if used judiciously!
Formatting Best Practices
Because ternary logic can quickly get complicated, follow these formatting guidelines:
- Align the ? and : operators vertically for easier visual parsing
- Use parenthesis around complex expressions for improved readability
- Break conditionals into multiple lines and stages when needed
- Maintain consistent and indented formatting per style guide
- Document complex business logic with comments
Proper formatting prevents dense ternary one-liners that demand excessive cognitive load to understand.
Prioritize readability first before brevity and compactness. Treat ternaries more as focused conditional assignments rather than complex logic flow.
Linting Rules
Many linters like ESLint recommend limiting nested ternary depth like so:
// Good
const value = condition ? x : y;
// Avoid
const value = condition ? x
: condition2 ? y : z;
// Limit to depth 2
const value = condition ?
(nestedCondition ? x : y)
: z;
They also enforce consistent spacing, indentation, and braces around expressions. Follow your team‘s lint configurations.
If opting to flatten complex ternaries manually, disable max depth warnings accordingly.
Caveats and Edge Cases
Be cognizant that deeply nested logic can be challenging to parse visually:
const value = ((a > 10 && b 30)
? ((x === 10) ? 10 : (y > 20) ? 20 : 30)
: ((z !== 25) ? 15
: (w > 40) ? 40
: 50)
Here despite heavy consistency formatting, unraveling the logical flow still proves daunting!
So the key again boils down to judiciously using ternaries only for straightforward boolean checks and assignments. For complex conditional flows, prefer if…else statements or a switch construct instead.
Operator Associativity
Another edge case to be aware of relates to Javascript‘s operator associativity rules.
Consider this example:
let msg = age > 30 ? ‘Old‘ : ‘Young‘;
msg = hairColor == ‘blonde‘ ? ‘Blonde‘ : msg;
The intent here seems to check first age predicate, before hair color to potentially override message.
But what actually happens:
The engine associates the ternary statements left to right. So it will evaluate the second ternary completely first, before checking the initial age condition!
This will produce likely unintended results. To avoid this evaluation order quirk, simplify into separate inline if statements.
Formating Consistency
Ternaries coded against team conventions or inconsistently can also Trip up readers:
const value = veryLongCondition ?
multiLineExpression :
otherExpression;
The mismatched line wrapping here is misleading and can cause mistaken assumptions.
So strive for visually symmetrical formatting.
Expert Coding Tips
Here are some pro tips when working with ternary operators:
- Temp variables: Store complex expressions in temps before ternary check
- Parens: Wrap confusing chunks in parens for improved readability
- Functions: Extract complex logic into well-named function calls
- Comments: Use comments for higher-level logic clarification
- Style rules: Ensure team conventions compliance
- Progressive disclosure: Gradually disclose details in stages
- Cognitive chunks: Break into bite-sized coherent units of logic vs. one huge expression
- Self-documenting: Craft the prose to tell a coherent story to the reader
Adhering to these practices distinguishes the truly proficient coders from novices. They achieve both brevity and readability.
Expert Coder Perspective
Here is some advice from my decade-plus professional experience for sustainably leveraging ternaries:
- Value transparency and self-documenting code
- Treat ternaries as focused, limited-scope tools
- Resist overzealous DRY adherence when readability suffers
- Flat, boring code tends to age better than clever one-liners
- Complexity/nesting depth Creeps gradually over time
- Prioritize descriptive flow above terseness
- Consume APIs favoring readability—drive change by example
- Influence through compassionate coaching, not demands
The key remains balancing conciseness and comprehension. Strive to craft clean prose translating logic flow into coherent narrative for the reader.
Wrap Up
The ternary operator offers a compact inline syntax for conditionally executing code blocks based on boolean checks. It serves as an alternative to verbose if/else statements.
We covered core syntax, use cases, performance advantages, and formatting best practices when working with ternaries. Always prioritize readability by limiting nesting depth and flattening complex expressions when viable.
Used judiciously, ternary operators enable cleaner inline conditional logic. But beware of overly terse obfuscated code and inconsistent formatting.
Evaluate each case based on context and analytics. Stick to community style guides. And refactor prudently when ternaries begin impairing comprehension.
Hopefully this guide offers a comprehensive expert-level overview into inline if statements within JavaScript!