How to Use Object.groupBy and Map.groupBy in JavaScript

Modern JavaScript introduces native collection grouping with Object.groupBy() and Map.groupBy(), eliminating the need for external utility libraries like Lodash or complex Array.prototype.reduce() implementations. This article covers how these two static methods work, their syntax, practical code examples, and the key differences between them to help you choose the right approach for your data.

The Problem with Traditional Grouping

Before these methods were standardized in ECMAScript 2024, grouping elements in an array required verbose boilerplate code using reduce():

const inventory = [
  { name: "Asparagus", type: "vegetables", quantity: 5 },
  { name: "Bananas", type: "fruit", quantity: 0 },
  { name: "Cherries", type: "fruit", quantity: 12 },
];

// The old way
const grouped = inventory.reduce((acc, item) => {
  const key = item.type;
  if (!acc[key]) {
    acc[key] = [];
  }
  acc[key].push(item);
  return acc;
}, {});

Native grouping replaces this boilerplate with a single, highly readable function call.

Using Object.groupBy()

Object.groupBy() accepts an iterable (such as an array) and a callback function that determines the group key for each element. It returns a null-prototype object where each key corresponds to a group containing an array of matched items.

Syntax

Object.groupBy(items, callbackFn)

Example: Grouping by a Property

const inventory = [
  { name: "Asparagus", type: "vegetables", quantity: 5 },
  { name: "Bananas", type: "fruit", quantity: 0 },
  { name: "Cherries", type: "fruit", quantity: 12 },
];

const result = Object.groupBy(inventory, ({ type }) => type);

console.log(result);
/* Output:
{
  vegetables: [
    { name: "Asparagus", type: "vegetables", quantity: 5 }
  ],
  fruit: [
    { name: "Bananas", type: "fruit", quantity: 0 },
    { name: "Cherries", type: "fruit", quantity: 12 }
  ]
}
*/

Example: Grouping by Conditional Logic

Keys do not have to be existing properties; you can compute them dynamically:

const stockStatus = Object.groupBy(inventory, ({ quantity }) => {
  return quantity > 0 ? "inStock" : "outOfStock";
});

console.log(stockStatus);
/* Output:
{
  inStock: [
    { name: "Asparagus", ... },
    { name: "Cherries", ... }
  ],
  outOfStock: [
    { name: "Bananas", ... }
  ]
}
*/

Using Map.groupBy()

Map.groupBy() functions identically to Object.groupBy(), but returns a standard JavaScript Map instead of a plain object. This is crucial when your grouping keys need to be complex data types, such as objects, functions, or primitives other than strings and symbols.

Syntax

Map.groupBy(items, callbackFn)

Example: Grouping with Complex Object Keys

In Object.groupBy(), object keys are automatically coerced into strings ("[object Object]"). Map.groupBy() preserves reference equality for keys:

const restockInfo = { urgency: "high" };
const normalInfo = { urgency: "low" };

const inventory = [
  { name: "Asparagus", quantity: 5 },
  { name: "Bananas", quantity: 0 },
  { name: "Cherries", quantity: 12 },
];

const groupedByPriority = Map.groupBy(inventory, ({ quantity }) => {
  return quantity === 0 ? restockInfo : normalInfo;
});

console.log(groupedByPriority.get(restockInfo));
// Output: [{ name: "Bananas", quantity: 0 }]

Key Differences: Object.groupBy vs Map.groupBy

Feature Object.groupBy() Map.groupBy()
Return Type Plain object with a null prototype Standard Map instance
Key Coercion Keys are converted to strings or symbols Preserves original key types (objects, numbers, etc.)
Access Method Property access (result.key or result['key']) Map methods (result.get(key), result.has(key))
Serialization Directly serializable to JSON via JSON.stringify() Requires conversion before JSON serialization

Runtime Support

Both Object.groupBy and Map.groupBy are standard JavaScript features supported across all modern web browsers (Chrome, Edge, Firefox, Safari) and server-side runtimes including Node.js (version 21 and above) and Deno.