You've been writing this reduce a hundred times. Object.groupBy does it in one.
Grouping an array by a key is one of the most common data transforms in frontend code. You've been wiring it by hand with `reduce` for years. `Object.groupBy` is the native version — no helper, no library, no ceremony.

Open any frontend codebase and search for .reduce. I'll wait.
A meaningful fraction of those hits look like this:
Or, if the author has been around long enough, this tighter variant:
Both do the same thing: group an array by a key. It's one of the most common data transforms in any frontend codebase — group tasks by status, events by date, errors by code, users by role. You've written it dozens of times because JavaScript never had a built-in name for it.
It does now. And it has been in every major browser since early 2024.
Pass an iterable and a callback. The callback returns the group key for each item. The result is a plain object where each key holds an array of the items that mapped to it.
The callback can return any value that stringifies to a useful key — a status enum, a date string, a category slug, a computed bucket. Items that map to the same string land in the same array. Items that would map to undefined land under the key "undefined", which is a sign you should add a fallback in the callback.
Runs right in your browser — poke at it and watch the concept react live.
Object.groupBy coerces every key to a string. That covers most cases. If you need to group by something that isn't meaningfully stringifiable — an object reference, a boolean you want distinct from the string "true", or any value where identity matters — Map.groupBy is the variant:
The result is a real Map, so you access values with .get() and iterate with .entries(). Keys are the exact values your callback returned — no stringification, no coercion, no surprises.
Before groupBy, building a Kanban-style board from a flat API response involved one of two patterns. Either a filter per lane:
That walks tasks once per lane — four passes for four columns. Or a reduce — one pass, but four lines of bookkeeping per developer who reads it.
With Object.groupBy:
One pass. No ceremony. The intent is in the function name.
Object.groupBy returns an object with a null prototype — Object.create(null). It has no inherited toString, hasOwnProperty, or any of the usual Object.prototype methods. It's a pure data dictionary.
For most real uses this is exactly right: no prototype key collisions, no need for the hasOwnProperty dance before accessing a key. If downstream code needs a normal prototype — say, you're serializing it with a library that calls toString — wrap it: Object.assign({}, grouped). But in practice you rarely need to.
Object.groupBy is Baseline 2024: Chrome 117, Firefox 119, Safari 17.4, Node.js 21. If your targets include browsers from the last two years you can use it today without a polyfill. For older targets a one-liner shim is trivial, but at this point you're more likely to just set a browserslist target that excludes the handful of users still on pre-2024 releases.
Think it clicked? Take the 6-question quiz →
Instant feedback, a hint on every question, and an explanation for each answer — right or wrong.
Object.groupBy isn't a convenience — it's the word for what you've been spelling out in four lines of reduce. Find the grouping reduces in your codebase, replace them, and delete whatever groupBy helper you wrote to avoid writing them inline. The operation has a name and a native implementation now; there's nothing left to carry.
Thanks for reading! Let's stay connected:
- ⭐ GitHub — follow me and star the projects: github.com/parsajiravand
- 💬 Discord — join the frontend best-practices community: discord.gg/d9KRhuAwQ
- 📸 Instagram — frontend best practices, daily: @bestpractice___
- 💼 LinkedIn — linkedin.com/in/parsa-jiravand
- ✉️ Email (work & contract inquiries): bestpractice2026@gmail.com
Originally published on dev.to