Practical JavaScript: Arrays vs. Objects | by Joe Boyle | Towards Data Science

Someone asked me today: “How do you know when to use an object, and when to use an array?” I couldn’t find a resource online that gave the answer I wanted, so... I will be the change I want to see.
Think about what your particular data represents: If it’s a single entity with named properties, you want an object. If it’s a group of entities of the same type/shape, or if order matters, you likely want an array.
If it’s still unclear, think about how you’ll be working with the data: manipulating individual properties? Object, probably. Doing manipulations over the data as a whole, or filtering and manipulating chunks of the data? An array, I’ll bet.
Also, if you’re working with existing data and it’s already an object or array, you probably wouldn’t convert it to another without good reason.
// A list of ordered strings is a good case for an array:const sortedNames = ['Axl', 'Billie', 'Chuck'];// An item with named properties is a good case for an object:const box = { height: 4, width: 3, color: 'blue' };
Arrays and objects are two ways of collecting data into a group. The data can be primitives (strings, numbers, booleans):
const namesArr = ['Danny', 'Donny', 'Joey', 'Jordan', 'Jonathan'];const userObj = { name: 'Jamie', age: 42 };
...or they can be made of other arrays or objects:
const usersArr = [{ name: 'Jim', age: 4 }, { name: 'Al', age: 62 }];const miscObj = { colors: ['orange', 'red'], numbers: [1, 2, 3] };
So, why would you pick one over the other? At the risk of oversimplifying, it comes down to ease-of-use and performance.
What do I mean by ease-of-use? When we group data together, we usually want to use it in some way. Specifically, we want to add elements, remove them, access/update them, or iterate over each of them.
Side note: the person asking was using React, so immutability is a concern, which has an impact on ease-of-use/readability. Mutable methods like push(), pop(), splice(), etc would make things simpler, but in these examples I’ll be thinking immutably. There are also a few different methods to achieve each of these examples (spread vs. concat, for instance), but I’ll just stick to one method.
Let’s say we have this array of names:
const names = ['Bob', 'Cate'];
We have a new name that we want to add one to either end. Easy!
const namesPlusEnd = [...names, 'Deb'];// ['Bob', 'Cate', 'Deb'];const namesPlusStart = ['Axl', ...names];// ['Axl', 'Bob', 'Cate'];
But when we want to insert a name into the middle of an array, we need to know the index. We can’t insert something unless we know where it needs to go, so if we don’t have the index, we need to find it using Array.findIndex, which takes time to iterate though the array.
const namesPlusMiddle = [  ...names.slice(0, 1),  'Bud',  ...names.slice(1)];// ['Bob', 'Bud', 'Cate']
Objects, on the other hand, don’t keep track of order, so it’s simple to add properties anywhere since there’s no concept of beginning/middle/end, and fast, since we don’t need to iterate:
const box = { width: 4, height: 3, color: 'blue' };If we care about immutability:const newBox = { ...box, id: 42 };Or, if we don't:box.id = 42;// box/newBox are both now:// { width: 4, height: 3, color: 'blue', id: 42 };
What about removing items? Again, it depends! Easy to remove from the beginning or end of an array:
const colors = ['red', 'green', 'blue'];const colorsWithoutFirst = colors.slice(1);// ['green', 'blue']const colorsWithoutLast = colors.slice(0, -1);// ['red', 'green']
Also pretty easy from the middle, but again, you need to know the index you want removed (in this case index 1), or iterate through to filter out the value:
const colorsMinusMid = [...colors.slice(0, 1), ...colors.slice(2)];// ['red', 'blue']const colorsMinusGreen = colors.filter(color => color !== 'green');// ['red', 'blue']
Like adding a property to an object, removing an object property is simple no matter where in the object (since there’s not really a concept of ‘where’ something is in an object).
Immutably:const { color, ...colorlessBox } = box;With mutation:delete box.color;colorlessBox/box are both now:// { height: 4, width: 3, id: 42 }
Updation - not a real word. When we want to update an element in an array, we can do it by index, or if we don’t know the index we can iterate over it looking for the element based on the element’s value (or a property on the element). Updating via iteration is common, since we often deal with large sets of data where we don’t know the index, or dynamic data where the index can change.
const fruits = ['apple', 'banana', 'clementine'];const newFruits = [  ...fruits.slice(0, 1),  'watermelon',   ...fruits.slice(1)];This is a little simpler, and leaves the fruits array unchanged:const fruitsCopy = fruits.slice();fruitsCopy[1] = 'watermelon';Or, if we don't know the index:const newFruits = fruits.map(fruit => {  if (fruit === 'banana') return 'watermelon';  return fruit;});// ['apple', 'watermelon', 'clementine'];
Updating an object, once again, is much more straightforward:
const box = { height: 4, width: 3, color: 'blue' };Immutably:const redBox = { ...box, color: 'red' };Mutably:box.color = 'red';// box/newBox are both now:// { height: 4, width: 3, color: 'red' }
If you just need to get the value of an element in an array (without updating it), it’s simple if you know the index, and not much harder if you don’t (but you know something about the element you’re looking for):
const fruits = ['apple', 'banana', 'clementine'];const secondFruit = fruits[1];// 'banana'const clementine = fruits.find(fruit => fruit === 'clementine');// 'clementine'
Accessing object properties is easy too:
const box = { width: 4, height: 3, color: 'blue' };const boxColor = box.color// 'blue'
So far, arrays have been kind of a drag compared to objects. Doing anything with a single array element requires that you know the index, or requires a bit more code. Finally, with iteration, it’s time for the array to shine. When you want do do some transformation to the elements as a batch, arrays are designed for this:
const fruits = ['apple', 'banana', 'clementine'];const capitalFruits = fruits.map(fruit => fruit.toUpperCase());// ['APPLE', 'BANANA', 'CLEMENTINE']fruits.forEach(fruit => console.log(fruit));// 'apple'// 'banana'// 'clementine'Iteration is common in React:const FruitsList = props => (  <ul>    {props.fruits.map(fruit => <li>{fruit}</li>)}  </ul>);// <ul>//   <li>apple</li>//   <li>banana</li>//   <li>clementine</li>// </ul>
To iterate over an object, our only real option is a for...in loop, but (in my opinion) it’s often simpler/more readable to just... convert it to an array. Object.keys/values/entries iterates over the keys, values, or both, and gives us an array of that data:
const box = { height: 4, width: 3, color: 'blue' };const BoxProperties = ({ box }) => (  <ul>    Object.keys(box).map(prop => <li>{prop}: {box[prop]}</li>);  </ul>);// <ul>//   <li>height: 4</li>//   <li>width: 3</li>//   <li>color: blue</li>// </ul>
Arrays also have other methods that allow you to work with the data, which objects don’t have:
const animalNames = ['ant', 'bird', 'centipede', 'demogorgon'];animalNames.reverse();// ['demogorgon', 'centipede', 'bird', 'ant']const shortNames = animalNames.filter(name => name.length < 5);// ['ant', 'bird'];const containsB = animalNames.some(name => name.includes('b'));// trueconst allAreLong = animalNames.every(name => name.length > 3);// falseconst totalLetters = animalNames.reduce((total, name) => {  return total + name.length;}, 0);// 26
You could implement any of these pretty easily with for...in, but arrays have them out of the box.
Speed isn’t always a consideration, but when it is there can be a big difference between arrays and objects. There are plenty of resources on the internet about array vs. object performance, but briefly: array manipulation is slower when you don’t know the index (linear time, or O(n)), because you have to iterate over each element until you find the one you’re looking to use. If you do know the index and immutability isn’t a concern, you don’t need to iterate and can access/update the element at that index quickly (constant time, or O(1)). Object property lookup/update/insertion/deletion happens quickly (also constant time) because the property name gives you a reference so you don’t have to go looking for the element you want.
The rule of thumb is: groups of similarly typed data, which you need ordered or want to manipulate as a batch are better suited for arrays, and grouped properties of a single entity are better suited for objects. Using the right data type isn’t always a clear choice, but the more you work with each data type, the more obvious it will be which one makes sense in any given situation.