Sling Academy
Home/JavaScript/Refactoring Conditional Logic into More Declarative Styles in JavaScript

Refactoring Conditional Logic into More Declarative Styles in JavaScript

Last updated: December 12, 2024

Refactoring conditional logic is a crucial skill for developers aiming to write clean, maintainable, and easy-to-read code. By transforming complex if-else structures into more declarative styles, you can improve the code's efficiency and readability. In JavaScript, there are several approaches to achieving this.

Understanding the Problem

Consider the following example, which is a typical representation of conditional logic in imperative style:

function getDiscountedPrice(price, discountType) {
  if (discountType === 'student') {
    return price * 0.8;
  } else if (discountType === 'senior') {
    return price * 0.7;
  } else if (discountType === 'veteran') {
    return price * 0.75;
  } else {
    return price;
  }
}

While this code is straightforward, it’s not flexible or easy to read, especially when extending beyond a few cases.

Using Object Literals for Lookup

A cleaner, more declarative approach is to use an object as a lookup for function references or values. Here's how the previous function can be refactored:

const discountRates = {
  student: 0.8,
  senior: 0.7,
  veteran: 0.75,
};

function getDiscountedPrice(price, discountType) {
  const rate = discountRates[discountType] || 1;
  return price * rate;
}

By using an object to store the discount rates, you can efficiently manage and extend the discount rules without modifying the logical flow.

Employing Functional Approaches

JavaScript's functional programming features allow a more declarative way using functions such as map, filter, and reduce. This is very effective in scenarios where you need to apply transformations or filters on an array based on conditions.

const products = [
  { name: 'laptop', price: 1000, category: 'electronics' },
  { name: 'shirt', price: 50, category: 'apparel' },
];

const discountedProducts = products.map(product => {
  const discount = discountRates[product.category] || 1;
  return { ...product, price: product.price * discount };
});

Through mapping, we transform each element based on logic derived from our lookup, reducing the need for cumbersome if-else statements.

Leveraging Switch Statements

For scenarios where enumerating cases is necessary and the number of conditions is fixed and small, switch statements might be more suitable than if-else:

function getDiscountDescription(discountType) {
  switch (discountType) {
    case 'student':
      return '20% off for students';
    case 'senior':
      return '30% off for seniors';
    case 'veteran':
      return '25% off for veterans';
    default:
      return 'No discount available';
  }
}

This usage augments readability and clearly delineates discrete scenarios.

Utilizing Early Returns

An often overlooked method to clean conditional logic is the 'early return technique.' It avoids deep nesting and clarifies the intended quick exit from the function when certain conditions are met:

function processTransaction(price, discountType) {
  if (!price) return 'Invalid price';
  const rate = discountRates[discountType] || 1;
  return `Total: $${price * rate}`;
}

This technique helps flatten the logic, making the function easier to trace.

Conclusion

Refactoring large and complex conditional statements into smaller, declarative structures can significantly improve code quality. Using object literals, functional programming techniques, switch statements, and early returns allow you to maintain and expand your application efficiently. Remember, the goal is not necessarily to eliminate all conditionals, but to manage them in a way that enhances code clarity and extendability.

Next Article: Leveraging Destructuring and Spread to Simplify Conditional Assignments in JavaScript

Previous Article: Aligning Code Structure with Common Control Flow Patterns for Better Readability in JavaScript

Series: Mastering Control Flow in JavaScript

JavaScript

You May Also Like

  • Handle Zoom and Scroll with the Visual Viewport API in JavaScript
  • Improve Security Posture Using JavaScript Trusted Types
  • Allow Seamless Device Switching Using JavaScript Remote Playback
  • Update Content Proactively with the JavaScript Push API
  • Simplify Tooltip and Dropdown Creation via JavaScript Popover API
  • Improve User Experience Through Performance Metrics in JavaScript
  • Coordinate Workers Using Channel Messaging in JavaScript
  • Exchange Data Between Iframes Using Channel Messaging in JavaScript
  • Manipulating Time Zones in JavaScript Without Libraries
  • Solving Simple Algebraic Equations Using JavaScript Math Functions
  • Emulating Traditional OOP Constructs with JavaScript Classes
  • Smoothing Out User Flows: Focus Management Techniques in JavaScript
  • Creating Dynamic Timers and Counters with JavaScript
  • Implement Old-School Data Fetching Using JavaScript XMLHttpRequest
  • Load Dynamic Content Without Reloading via XMLHttpRequest in JavaScript
  • Manage Error Handling and Timeouts Using XMLHttpRequest in JavaScript
  • Handle XML and JSON Responses via JavaScript XMLHttpRequest
  • Make AJAX Requests with XMLHttpRequest in JavaScript
  • Customize Subtitle Styling Using JavaScript WebVTT Integration