JavaScript Ternary Operator
Ternary Operator Basics
The ternary operator is the only JavaScript operator that takes three operands. It provides a shorthand way to write simple if-else statements and returns a value based on a condition. The ternary operator is also known as the conditional operator.
1// Basic ternary operator syntax
2let age = 20;
3let canVote = (age >= 18) ? "Yes" : "No";
4console.log(canVote); // Output: "Yes"
5
6// Syntax breakdown:
7// condition ? expressionIfTrue : expressionIfFalse
8//
9// Step-by-step execution:
10// 1. Evaluate condition: (age >= 18) → true
11// 2. Since condition is true, return first expression "Yes"
12// 3. Assign "Yes" to canVote variable
13
14// More examples:
15let temperature = 25;
16let weatherMessage = (temperature > 30) ? "Hot" : "Comfortable";
17console.log(weatherMessage); // Output: "Comfortable"
18
19let isRaining = true;
20let activity = isRaining ? "Stay indoors" : "Go outside";
21console.log(activity); // Output: "Stay indoors"
22
23// Without parentheses (still works)
24let score = 85;
25let grade = score >= 90 ? "A" : "B";
26console.log(grade); // Output: "B"Ternary Operator Core Components
Three Operands- Condition, true expression, false expressionReturns Value- Evaluates to one of the two expressionsExpression-Based- Can be used anywhere an expression is validShort-Circuit Evaluation- Only one branch is evaluated
Ternary Operator Syntax and Structure
Understanding the complete syntax and structure of ternary operators is crucial for writing clean and effective conditional expressions. The operator follows a consistent pattern with specific rules for each part.
1// Complete ternary syntax breakdown
2
3// 1. Basic assignment
4let age = 20;
5let status = (age >= 18) ? "Adult" : "Minor";
6console.log(status); // Output: "Adult"
7
8// 2. Direct usage without assignment
9console.log(age >= 21 ? "Can drink" : "Cannot drink"); // Output: "Cannot drink"
10
11// 3. In template literals
12let name = "Alice";
13let isAdmin = true;
14console.log(`Welcome ${isAdmin ? "Admin" : "User"} ${name}`); // Output: "Welcome Admin Alice"
15
16// 4. In function arguments
17function greetUser(role) {
18 console.log(`Hello, ${role === 'admin' ? 'Administrator' : 'User'}`);
19}
20greetUser('admin'); // Output: "Hello, Administrator"
21
22// 5. With multiple operations (using comma operator)
23let count = 5;
24let result = (count > 0) ? (console.log("Positive"), "Valid") : "Invalid";
25console.log(result); // Output: "Positive" then "Valid"
26
27// 6. Returning objects
28let userType = "premium";
29let userConfig = userType === "premium" ? { theme: "dark", ads: false } : { theme: "light", ads: true };
30console.log(userConfig); // Output: { theme: "dark", ads: false }
31
32// 7. Returning functions
33let operation = "add";
34let mathFunction = operation === "add" ? (a, b) => a + b : (a, b) => a - b;
35console.log(mathFunction(5, 3)); // Output: 8
36
37// 8. With array methods
38let numbers = [1, 2, 3, 4, 5];
39let doubled = numbers.map(num => num % 2 === 0 ? num * 2 : num);
40console.log(doubled); // Output: [1, 4, 3, 8, 5]
41
42// Syntax rules:
43// - Condition before ?
44// - True expression between ? and :
45// - False expression after :
46// - Parentheses are optional but recommended for clarityTernary Syntax Components
condition ?- Boolean expression that determines which branch to takeexpressionIfTrue- Expression evaluated and returned if condition is true: expressionIfFalse- Expression evaluated and returned if condition is falseExpression Context- Can be used anywhere expressions are valid
Ternary Operator vs If-Else Statements
Understanding when to use ternary operators versus traditional if-else statements is crucial for writing clean, maintainable code. Each has its strengths and appropriate use cases.
1// Scenario 1: Simple value assignment - TERNARY is better
2let age = 20;
3
4// Ternary version (concise)
5let canVote = age >= 18 ? "Yes" : "No";
6
7// If-else version (more verbose)
8let canVoteIfElse;
9if (age >= 18) {
10 canVoteIfElse = "Yes";
11} else {
12 canVoteIfElse = "No";
13}
14
15console.log(canVote); // Output: "Yes"
16console.log(canVoteIfElse); // Output: "Yes"
17
18// Scenario 2: Multiple statements - IF-ELSE is better
19let user = { name: "Alice", role: "admin" };
20
21// If-else version (better for multiple operations)
22if (user.role === "admin") {
23 console.log("Admin logged in");
24 sendAdminNotification();
25 updateAdminDashboard();
26} else {
27 console.log("User logged in");
28 updateUserActivity();
29}
30
31// Ternary would be awkward for multiple statements
32// user.role === "admin" ? (console.log("Admin"), notify(), update()) : (console.log("User"), updateActivity())
33
34// Scenario 3: Multiple conditions - IF-ELSE IF is better
35let score = 85;
36
37// If-else if version (clearer for multiple conditions)
38let grade;
39if (score >= 90) {
40 grade = "A";
41} else if (score >= 80) {
42 grade = "B";
43} else if (score >= 70) {
44 grade = "C";
45} else {
46 grade = "F";
47}
48
49// Nested ternary (hard to read)
50let gradeTernary = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : "F";
51
52console.log(grade); // Output: "B"
53console.log(gradeTernary); // Output: "B"
54
55// Scenario 4: Return values in functions - TERNARY is better
56function getDiscount(isMember, total) {
57 // Ternary version (clean)
58 return isMember ? total * 0.1 : total * 0.05;
59
60 // If-else version (more code)
61 // if (isMember) {
62 // return total * 0.1;
63 // } else {
64 // return total * 0.05;
65 // }
66}
67
68console.log(getDiscount(true, 100)); // Output: 10
69
70// Scenario 5: Conditional object properties - TERNARY is better
71let isDarkMode = true;
72let themeSettings = {
73 mode: isDarkMode ? "dark" : "light",
74 colors: isDarkMode ? { primary: "#000", secondary: "#333" } : { primary: "#fff", secondary: "#eee" }
75};
76
77console.log(themeSettings.mode); // Output: "dark"
78
79// Guidelines:
80// - Use TERNARY for: simple value assignments, return statements, template literals
81// - Use IF-ELSE for: multiple statements, complex logic, side effects
82// - Avoid nested ternaries for more than 2 levelsNested Ternary Operators
Ternary operators can be nested to handle multiple conditions, but this should be done cautiously as deeply nested ternaries can become difficult to read and maintain.
1// Nested ternary operators - use with caution!
2
3// Example 1: Simple nested ternary
4let score = 85;
5let grade = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : "F";
6console.log(grade); // Output: "B"
7
8// Equivalent if-else:
9// if (score >= 90) {
10// grade = "A";
11// } else if (score >= 80) {
12// grade = "B";
13// } else if (score >= 70) {
14// grade = "C";
15// } else {
16// grade = "F";
17// }
18
19// Example 2: Multiple conditions with nesting
20let age = 25;
21let hasLicense = true;
22let driveStatus = age >= 18 ? (hasLicense ? "Can drive" : "Needs license") : "Too young";
23console.log(driveStatus); // Output: "Can drive"
24
25// Example 3: Complex nested ternary (hard to read - avoid!)
26let user = { role: "moderator", isActive: true, isBanned: false };
27let accessLevel =
28 user.role === "admin" ? "full" :
29 user.role === "moderator" ? (user.isActive ? "moderate" : "restricted") :
30 user.isActive && !user.isBanned ? "basic" : "none";
31
32console.log(accessLevel); // Output: "moderate"
33
34// Better approach: Break into variables or functions
35function getAccessLevel(user) {
36 if (user.role === "admin") return "full";
37 if (user.role === "moderator") return user.isActive ? "moderate" : "restricted";
38 return user.isActive && !user.isBanned ? "basic" : "none";
39}
40
41console.log(getAccessLevel(user)); // Output: "moderate"
42
43// Example 4: Formatting nested ternaries for readability
44let temperature = 25;
45let weather = "sunny";
46
47// Poor formatting (hard to read)
48let suggestion = temperature > 30 ? weather === "sunny" ? "Go swimming" : "Stay indoors" : weather === "rainy" ? "Take umbrella" : "Enjoy walk";
49
50// Better formatting with line breaks and parentheses
51let betterSuggestion =
52 temperature > 30
53 ? (weather === "sunny" ? "Go swimming" : "Stay indoors")
54 : (weather === "rainy" ? "Take umbrella" : "Enjoy walk");
55
56console.log(betterSuggestion); // Output: "Enjoy walk"
57
58// Example 5: Using helper functions instead of deep nesting
59function getTemperatureSuggestion(temp, weather) {
60 if (temp > 30) {
61 return weather === "sunny" ? "Go swimming" : "Stay indoors";
62 } else {
63 return weather === "rainy" ? "Take umbrella" : "Enjoy walk";
64 }
65}
66
67console.log(getTemperatureSuggestion(25, "sunny")); // Output: "Enjoy walk"
68
69// Best practices for nested ternaries:
70// - Limit to 2-3 levels maximum
71// - Use proper formatting and parentheses
72// - Consider if-else for complex logic
73// - Extract complex conditions into helper functionsAdvanced Ternary Patterns and Techniques
Ternary operators can be used in various advanced patterns for concise and expressive code. Understanding these patterns helps you leverage ternaries effectively in different scenarios.
1// Pattern 1: Short-circuit evaluation with ternary
2let user = null;
3let username = user ? user.name : "Anonymous";
4console.log(username); // Output: "Anonymous"
5
6// Pattern 2: Default parameter simulation
7function greet(name) {
8 return `Hello, ${name ? name : "Guest"}`;
9}
10console.log(greet("Alice")); // Output: "Hello, Alice"
11console.log(greet()); // Output: "Hello, Guest"
12
13// Pattern 3: Conditional function execution
14let isDevelopment = true;
15let logMessage = isDevelopment
16 ? (message) => console.log("DEV:", message)
17 : () => {}; // No-op in production
18
19logMessage("Debug info"); // Output: "DEV: Debug info"
20
21// Pattern 4: Conditional object property assignment
22let config = {
23 apiUrl: "https://api.example.com",
24 ...(process.env.NODE_ENV === "development" ? { debug: true, logging: "verbose" } : {})
25};
26console.log(config); // Includes debug properties in development
27
28// Pattern 5: Array conditional filtering and mapping
29let numbers = [1, 2, 3, 4, 5];
30let processed = numbers.map(num =>
31 num % 2 === 0 ? { value: num, type: "even" } : { value: num, type: "odd" }
32);
33console.log(processed);
34// Output: [{value:1,type:"odd"}, {value:2,type:"even"}, ...]
35
36// Pattern 6: Conditional class names (common in React)
37let isActive = true;
38let isError = false;
39let className = `button ${isActive ? "active" : ""} ${isError ? "error" : ""}`.trim();
40console.log(className); // Output: "button active"
41
42// Pattern 7: Conditional import/require (conceptual)
43// const logger = DEBUG ? require('./detailed-logger') : require('./basic-logger');
44
45// Pattern 8: Mathematical operations
46let a = 5, b = 10;
47let max = a > b ? a : b;
48let min = a < b ? a : b;
49console.log(`Max: ${max}, Min: ${min}`); // Output: "Max: 10, Min: 5"
50
51// Pattern 9: String formatting
52let count = 1;
53let itemText = count === 1 ? "item" : "items";
54console.log(`${count} ${itemText}`); // Output: "1 item"
55
56// Pattern 10: Conditional event handlers
57let button = {
58 onClick: null,
59 label: "Click me"
60};
61
62let hasHandler = true;
63button.onClick = hasHandler ? () => console.log("Clicked!") : null;
64
65// Pattern 11: State machine transitions
66let currentState = "idle";
67let action = "start";
68
69let nextState =
70 currentState === "idle" && action === "start" ? "running" :
71 currentState === "running" && action === "stop" ? "idle" :
72 currentState;
73
74console.log(nextState); // Output: "running"
75
76// Pattern 12: Feature flags
77const FEATURES = {
78 NEW_UI: true,
79 ANALYTICS: false,
80 DARK_MODE: true
81};
82
83let uiComponent = FEATURES.NEW_UI ? NewComponent : OldComponent;
84let shouldTrack = FEATURES.ANALYTICS ? trackEvent : () => {};
85
86// Pattern 13: Conditional validation messages
87let email = "";
88let validationMessage =
89 !email ? "Email is required" :
90 !email.includes("@") ? "Invalid email format" :
91 "Valid email";
92
93console.log(validationMessage); // Output: "Email is required"
94
95// Pattern 14: Price formatting with conditions
96let price = 99.99;
97let currency = "USD";
98let formattedPrice =
99 currency === "USD" ? `$${price}` :
100 currency === "EUR" ? `€${price}` :
101 `${price} ${currency}`;
102
103console.log(formattedPrice); // Output: "$99.99"Common Ternary Operator Mistakes
Understanding common mistakes with ternary operators helps you write more robust and bug-free code. These pitfalls often lead to unexpected behavior and hard-to-find issues.
1// Mistake 1: Forgetting the else clause
2let age = 20;
3
4// WRONG - missing : and false expression
5// let status = (age >= 18) ? "Adult"; // SyntaxError
6
7// CORRECT - always include both expressions
8let status = (age >= 18) ? "Adult" : "Minor";
9
10// Mistake 2: Using for side effects instead of values
11let count = 0;
12
13// WRONG - using ternary for side effects (hard to read)
14// (count > 0) ? console.log("Positive") : console.log("Non-positive");
15
16// CORRECT - use if-else for side effects
17if (count > 0) {
18 console.log("Positive");
19} else {
20 console.log("Non-positive");
21}
22
23// CORRECT ALTERNATIVE - if you must use ternary
24let message = count > 0 ? "Positive" : "Non-positive";
25console.log(message);
26
27// Mistake 3: Incorrect operator precedence
28let a = 5, b = 10;
29
30// WRONG - + has higher precedence than ?:
31// let result = a > b ? "Bigger" : "Smaller" + " than b"; // "Smaller than b" when false
32
33// CORRECT - use parentheses
34let result = a > b ? "Bigger" : ("Smaller" + " than b");
35console.log(result); // Output: "Smaller than b"
36
37// BETTER - use template literals
38let betterResult = a > b ? "Bigger" : `Smaller than b`;
39
40// Mistake 4: Deep nesting (unreadable code)
41let user = { role: "user", isActive: true, isVerified: false };
42
43// WRONG - deeply nested ternary
44let access = user.role === "admin" ? "full" : user.role === "moderator" ? user.isActive ? "moderate" : "limited" : user.isVerified ? "basic" : "none";
45
46// CORRECT - break into multiple statements or use if-else
47let userAccess;
48if (user.role === "admin") {
49 userAccess = "full";
50} else if (user.role === "moderator") {
51 userAccess = user.isActive ? "moderate" : "limited";
52} else {
53 userAccess = user.isVerified ? "basic" : "none";
54}
55
56// Mistake 5: Not considering falsy values properly
57let username = "";
58
59// WRONG - empty string is falsy, might not be intended
60let displayName = username ? username : "Anonymous";
61console.log(displayName); // Output: "Anonymous" (might be unexpected)
62
63// CORRECT - check specifically for null/undefined if that's the intent
64let correctDisplayName = username !== null && username !== undefined ? username : "Anonymous";
65
66// OR use nullish coalescing if appropriate
67let modernDisplayName = username ?? "Anonymous";
68
69// Mistake 6: Using ternary when if-else is clearer
70let items = [1, 2, 3];
71
72// WRONG - ternary for multiple operations
73// items.length > 0 ? (console.log("Processing"), processItems(items)) : console.log("No items");
74
75// CORRECT - if-else for multiple operations
76if (items.length > 0) {
77 console.log("Processing");
78 processItems(items);
79} else {
80 console.log("No items");
81}
82
83function processItems(items) {
84 console.log("Processing", items.length, "items");
85}
86
87// Mistake 7: Not using parentheses for complex conditions
88let x = 5, y = 10, z = 15;
89
90// WRONG - unclear precedence
91// let complexResult = x > y && y < z ? "Condition met" : "Not met";
92
93// CORRECT - use parentheses for clarity
94let complexResult = (x > y && y < z) ? "Condition met" : "Not met";
95
96// Mistake 8: Returning different types
97let condition = true;
98
99// WRONG - returning different types can be confusing
100let confusing = condition ? "String" : 42;
101
102// CORRECT - try to return consistent types
103let consistent = condition ? "True string" : "False string";
104
105// Mistake 9: Not considering performance with function calls
106function expensiveOperation() {
107 console.log("This is expensive!");
108 return "expensive result";
109}
110
111function cheapOperation() {
112 return "cheap result";
113}
114
115// WRONG - both functions are called!
116// let output = true ? expensiveOperation() : cheapOperation();
117
118// CORRECT - use if-else to avoid unnecessary calls
119let finalOutput;
120if (true) {
121 finalOutput = expensiveOperation();
122} else {
123 finalOutput = cheapOperation();
124}Ternary Operator Best Practices
Following established best practices for ternary operators leads to more readable, maintainable, and bug-free code. These guidelines help you write clean and effective conditional expressions.
1// Best Practice 1: Use for simple value assignments
2let age = 20;
3let canVote = age >= 18 ? "Yes" : "No"; // GOOD
4
5// Best Practice 2: Use parentheses for complex conditions
6let a = 5, b = 10, c = 15;
7let isValid = (a > 0 && b < 20) || c === 15 ? "Valid" : "Invalid"; // GOOD
8
9// Best Practice 3: Keep ternaries simple and single-purpose
10let user = { name: "Alice", role: "admin" };
11let welcomeMessage = user.role === "admin" ? "Welcome Admin" : "Welcome User"; // GOOD
12
13// Avoid complex logic in ternaries
14// let badMessage = user.role === "admin" ? (user.isActive ? "Active Admin" : "Inactive Admin") : "User"; // AVOID
15
16// Best Practice 4: Use consistent formatting
17let score = 85;
18
19// GOOD - consistent spacing and line breaks
20let result =
21 score >= 90 ? "Excellent" :
22 score >= 80 ? "Good" :
23 score >= 70 ? "Average" : "Poor";
24
25// Best Practice 5: Prefer ternaries for return statements
26function getPriceLabel(price) {
27 return price > 100 ? "Expensive" : "Affordable"; // GOOD
28}
29
30// Best Practice 6: Use descriptive variable names
31const isUserEligible = age >= 18 && hasId; // GOOD
32const eligibilityStatus = isUserEligible ? "Eligible" : "Not Eligible";
33
34// const x = y > z ? "A" : "B"; // BAD - unclear names
35
36// Best Practice 7: Avoid nested ternaries beyond 2 levels
37let userRole = "moderator";
38let isActive = true;
39
40// OK - 2 levels max
41let accessLevel = userRole === "admin" ? "full" : isActive ? "basic" : "none";
42
43// BAD - too deep
44// let badAccess = userRole === "admin" ? "full" : userRole === "moderator" ? isActive ? "moderate" : "restricted" : "none";
45
46// Best Practice 8: Use for template literals
47let itemCount = 1;
48let message = `You have ${itemCount} ${itemCount === 1 ? "item" : "items"}`; // GOOD
49
50// Best Practice 9: Consider readability over brevity
51let temperature = 25;
52
53// GOOD - clear and readable
54let clothingSuggestion = temperature > 20 ? "T-shirt" : "Jacket";
55
56// QUESTIONABLE - might be harder to understand
57// let suggestion = temp > 20 ? "T" : "J";
58
59// Best Practice 10: Use with array methods appropriately
60let numbers = [1, 2, 3, 4, 5];
61
62// GOOD - simple transformation
63let processed = numbers.map(n => n % 2 === 0 ? n * 2 : n);
64
65// Best Practice 11: Handle null/undefined explicitly
66let userName = null;
67
68// GOOD - explicit check
69let displayName = userName !== null && userName !== undefined ? userName : "Guest";
70
71// BETTER - use nullish coalescing when appropriate
72let modernName = userName ?? "Guest";
73
74// Best Practice 12: Document complex ternaries
75let config = {
76 // Use dark theme for admins, light for others
77 theme: user.role === "admin" ? "dark" : "light"
78};
79
80// Best Practice 13: Test both branches
81function testTernary() {
82 let input = 10;
83 let output = input > 5 ? "Greater" : "Less";
84
85 // Test cases
86 console.assert((5 > 5 ? "Greater" : "Less") === "Less", "Should return Less");
87 console.assert((6 > 5 ? "Greater" : "Less") === "Greater", "Should return Greater");
88}
89
90testTernary();
91
92// Best Practice 14: Know when to use alternatives
93let value = null;
94
95// For null/undefined checks, consider:
96let result1 = value ?? "default"; // Nullish coalescing
97let result2 = value || "default"; // Logical OR
98let result3 = value ? value : "default"; // Ternary
99
100console.log(result1, result2, result3); // All output: "default"