Illustrated key

Treat Javascript Objects like Arrays with Object.keys()

Whether you’re managing the state of your React application or parsing a JSON response from an API, objects and arrays are the key to data analysis in javascript. To a certain extent, the two overlap. That isn’t just because arrays are actually objects themselves, it’s also because plenty of data could be represented equally well by either structure. If you’re representing the day’s weather, you could use an object:

const weather = {
  date: '04/12',
  desc: 'Partly cloudy',
  high: 45,
  low: 34,
  precipitation: .2
}

Or you could use an array:

const weather = [ '04/12', 'Partly cloudy', 45, 34, .2 ]

However, even this simple example illustrates the trade-off between javascript’s two most used high-level data structures. With an object, I can retrieve the low temperature just by asking for it with weather.low. The array, on the other hand, requires me to know the index, which can change as items are added or subtracted. Arrays make up for this drawback with a whole host of useful methods for manipulating data. Let’s say I have a list of high temperatures for the month of April, and I want to find out how many days the temperature reached 40.

[ 35, 44, 58, 38, 41].filter( temp => temp >= 40 ).length

Handy methods like .filter, .map, .find can’t be called on objects – at least, not directly. Objects allow easy access to data, provided you know what key that data is stored under, but arrays are better for analysis.

It’s not one vs the other though. In reality, objects and arrays are meant to be used in concert, nested inside each other, each harmoniously playing its role. I only call attention to their differing strengths as a way of highlighting a mistake I would make early in my JS career when I wanted to perform some kind of filtering or lookup operation on an object the way I was used to doing with arrays. Let’s say I have this object, unrealistic as it is:

const obj = {
  prop1: false,
  prop2: true,
  prop3: false,
}

I want to find the property whose value is ‘true’. It this were an array i could use .indexOf. But since this is an object and array methods are unavailable, I would resort to a for...in loop:

let trueProp;
for ( let prop in obj ){
  if ( obj[prop] === true ){
    trueProp = prop;
  }
}

Ouch. Pawing through the object one key at a time with a loop feels very clumsy. And that goes back to the strengths of objects vs arrays – objects make it really easy to pick out a scrap of data, but only if you already know where that data is. In this scenario, you don’t know ahead of time which key is the ‘true’ one. If only there were a way to call array methods on objects.

Well, of course, there is. Object.keys() returns an “array whose elements are strings corresponding to the enumerable properties found directly upon [an] object” (MDN). Such a useful method! For all intents and purposes, it converts objects into arrays, using the keys of your object as a proxy through which you can call those juicy array methods on the object itself. Instead of that unwieldy for...in loop, you can just do:

const obj = {
  prop1: false,
  prop2: true,
  prop3: false,
}
const trueProp = Object.keys(obj).find( key => obj[key] === true );
console.log( trueProp );//"prop2"

Object.keys() gets you an array containing props 1-3, and then, because you have an array, you can now call .find() to return the key with the desired value.

It not that Object.keys() is an exotic programming technique. Really, it’s about as meat-and-potatoes a method as there is in JS. What’s cool about it is how it marries the strengths of two data structures, an object’s granular control over data with the iterative abilities of an array. Given that you don’t always have control over the exact format of your data, that’s a nice tool to have.