The Magic of Object Lookup

Photo by dylan nolte on Unsplash

The Magic of Object Lookup

An if...else and switch statement alternative

Hot take: if...else and switch both suck*

* In certain circumstances

A solution to a problem of conditional outcomes I came across early on in my JavaScript learning journey is the object lookup method. It reduces messy or visually overwhelming code to something that I believe is far more elegant and readable. I have implemented it is a couple of the "Learn JavaScript" projects I have completed.

It has its limitations of course--at least limitations that I have come to believe exist--but in simple enough application, it is superior to alternatives, including ternary.

In a nutshell, switch is just plain bloated and ugly and if...else can quickly get out of hand if there are too many options, if there is nested if...else, etc.

ryan-reynolds-but-why.gif

Take for example a function that returns the name of the day of a week, given a number from 1-7 inclusive.

The if...else solution

Longform if...else is "readable", sure, and not "complex", but looking at it one might get the feeling that there are "too many lines of code to accomplish something relatively simple".

// Longform if...else
const getDayOfWeekLong = num => {
  if (num === 1) {
    return 'Sunday'
  } else if (num === 2) {
    return 'Monday'
  } else if (num === 3) {
    return 'Tuesday'
  } else if (num === 4) {
    return 'Wednesday'
  } else if (num === 5) {
    return 'Thursday'
  } else if (num === 6) {
    return 'Friday'
  } else if (num === 7) {
    return 'Saturday'
  } else {
    return 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
  }
}

Even the ternary version--while somewhat more terse and readable--is something that when NOT formatted in the way seen immediately below, is wildly unreadable.

// Ternary if...else - formatted to be readable
const getDayOfWeekTernary = num => {
  return (num === 1) ? 'Sunday'
  : (num === 2) ? 'Monday'
  : (num === 3) ? 'Tuesday'
  : (num === 4) ? 'Wednesday'
  : (num === 5) ? 'Thursday'
  : (num === 6) ? 'Friday'
  : (num === 7) ? 'Saturday'
  : 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
}

Dear god ... why ...

// Ternary if...else - unformatted
const getDayOfWeekTernary = num => {
  return (num === 1) ? 'Sunday' : (num === 2) ? 'Monday' : (num === 3) ? 'Tuesday' : (num === 4) ? 'Wednesday' : (num === 5) ? 'Thursday' : (num === 6) ? 'Friday' : (num === 7) ? 'Saturday' : 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
}

The switch solution

This one is especially annoying and ugly. It's easy enough to read along and understand what can/will happen--I'll concede there--but sheer the amount of lines is even more than if...else.

Imagine if this had 20+ options!

const getDayOfWeekSwitch = num => {
  let day;
  switch(num) {
    case 1:
      day = 'Sunday';
      break;
    case 2:
      day = 'Monday';
      break;
    case 3:
      day = 'Tuesday';
      break;
    case 4:
      day = 'Wednesday';
      break;
    case 5:
      day = 'Thursday';
      break;
    case 6:
      day = 'Friday';
      break;
    case 7:
      day = 'Saturday';
      break;
    default:
      day = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
  }
  return day;
}

Object lookup to the rescue

This can be further simplified by using return {...}[num] || ....

const getDayOfWeekLookup = num => {
  let weekdays = {
    1: 'Sunday',
    2: 'Monday',
    3: 'Tuesday',
    4: 'Wednesday',
    5: 'Thursday',
    6: 'Friday',
    7: 'Saturday'
  }
  return weekdays[num] || 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
}

A challenger appears

Equally as elegant as object lookup (though perhaps less readable) is array lookup.

const getDayOfWeekArray = num => {
  let weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 
                  'Thursday', 'Friday', 'Saturday'];
  return weekdays[num - 1] || 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
}

Limitations

One limitation that comes to mind is say checking an input against a series of comparison operator and/or logical operator statements.

For example, in a function that returns a letter grade given a number input (e.g. 95), we can check the number against a series of if...else. if...else works. Object lookup does not work.

if...else

const getLetterGrade = num => {
  if (num >= 90 && num <= 100) {
    return 'A'
  } else if (num >= 80 && num <= 89) {
    return 'B'
  } // Rest of the logic
  else {
    return 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
  }
}

Object lookup

// This simply will not work
const getLetterGradeLookup = num => {
  return {
    (num >= 90 && num <= 100): 'A',
    // Rest of the options
  }[num] || 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
}

Conclusion

As seen above, there are multiple alternatives to if...else, one of which (guess which one [object lookup]) is superior to if...else, and vastly superior to switch.

HOWEVER, object lookup has its limitations in certain situations. It cannot process logical and comparison operators in the key-value pair arrangement objects rely on.