How to convert an object to an array in JavaScript?
Convert an object to an array with Object.keys, Object.values or Object.entries, go back with Object.fromEntries, and handle array-like objects.
Use Object.keys() for an array of the keys, Object.values() for the values, or Object.entries() for [key, value] pairs. All three return a new array and leave the object as it is.
const prices = { apple: 1.2, banana: 0.5, cherry: 3 };
Object.keys(prices);
// ['apple', 'banana', 'cherry']
Object.values(prices);
// [1.2, 0.5, 3]
Object.entries(prices);
// [['apple', 1.2], ['banana', 0.5], ['cherry', 3]]Pick the one that matches what you need next. If you only sum the prices, Object.values is enough. If you need both the name and the price, use Object.entries.
Entries to an array of objects
APIs often return an object keyed by id or name, while a list component wants an array of objects. Destructure each pair in map:
const products = Object.entries(prices).map(([name, price]) => ({
name,
price,
}));
// [
// { name: 'apple', price: 1.2 },
// { name: 'banana', price: 0.5 },
// { name: 'cherry', price: 3 }
// ]The parentheses around { name, price } are needed, because an arrow function reads a bare { as the start of a function body.
Back to an object with Object.fromEntries
Object.fromEntries() does the opposite of Object.entries(). It takes an array of [key, value] pairs and builds an object:
const backToObject = Object.fromEntries(
products.map(({ name, price }) => [name, price])
);
// { apple: 1.2, banana: 0.5, cherry: 3 }Together they're the usual way to map over an object, since objects have no map method of their own:
const doubled = Object.fromEntries(
Object.entries(prices).map(([name, price]) => [name, price * 2])
);
// { apple: 2.4, banana: 1, cherry: 6 }Which keys are included
All three methods return only the object's own enumerable string keys. They skip:
- inherited properties from the prototype,
- properties defined as non-enumerable,
Symbolkeys.
const base = { inherited: true };
const user = Object.create(base);
user.name = 'Ada';
user[Symbol('id')] = 42;
Object.defineProperty(user, 'secret', {
value: 'hidden',
enumerable: false,
});
Object.keys(user); // ['name']
user.inherited; // true, but it isn't in the arrayFor plain objects from JSON this never matters. It matters with class instances, where methods live on the prototype and won't show up.
Key order
The order is mostly insertion order, with one exception: keys that look like non-negative integers come first, sorted in ascending order. All keys also come back as strings.
const scores = { b: 1, 10: 'ten', a: 2, 2: 'two' };
Object.keys(scores);
// ['2', '10', 'b', 'a']If order matters and your keys are numeric ids, don't rely on the object. Sort the array yourself after converting, or keep the data in an array or a Map, which always keeps insertion order.
Array-like objects and NodeList
An array-like object has a length and indexed keys, but no array methods. Object.values is the wrong tool here, because it includes length as a value:
const arrayLike = { length: 2, 0: 'a', 1: 'b' };
Object.values(arrayLike);
// ['a', 'b', 2]
Array.from(arrayLike);
// ['a', 'b']The same goes for DOM collections. querySelectorAll returns a NodeList, which has forEach but no map or filter. Convert it with Array.from() or spread syntax:
const items = document.querySelectorAll('.menu li');
const labels = Array.from(items, (item) => item.textContent);
// or, the same with spread
const sameLabels = [...items].map((item) => item.textContent);Array.from takes a mapping function as the second argument, so you can convert and map in one step.