Oct 19, 2026
Stop paying for rows you never render.
Your dashboard table shows 25 rows, but the `.filter().map().slice()` chain processes all 50,000 first. ES2025 iterator helpers make the pipeline lazy — only the rows you render get touched.
A dashboard table I worked on showed 25 rows per page. The code behind it processed 50,000.
const page = rows
.filter(r => r.status === 'active') // new array: 50,000 items
.map(r => toRow(r)) // new array: 50,000 items
.slice(0, 25); // finally, the 25 we wanted
Three passes over the full dataset. Two throwaway intermediate arrays. All to render 25 rows. On a fast machine you never notice. On a mid-range phone loading a data-heavy view, you notice.
This is the eager tax: array methods do all the work up front, whether you need it or not.
Lazy instead
ES2025 gave iterators the same chainable API, but lazy — nothing runs until you pull a value:
const page = rows.values()
.filter(r => r.status === 'active') // pending
.map(r => toRow(r)) // pending
.take(25) // stop after 25
.toArray(); // NOW it runs — 25 rows processed
No intermediate arrays. The pipeline pulls one item at a time through filter → map, and take(25) stops the whole thing after 25 matches. The other 49,975 rows are never touched.
Where this actually matters
Not everywhere. For a few hundred items, array methods are fine — arguably clearer. The iterator version earns its keep when:
- Paginated tables over large datasets — the exact case above. You render a page, not the dataset.
- Search-as-you-type —
.filter(predicate).take(10)stops at 10 matches instead of scanning everything. - Chained transformations on chart data — aggregating thousands of points down to a few hundred for rendering.
The mental model: array methods answer "give me everything, then I'll pick." Iterator helpers answer "give me what I ask for, and stop when I say stop."
The details worth knowing
rows.values() turns any array into an iterator. Iterator.from() works on any iterable — Sets, Maps, generators. The method list mirrors arrays: map, filter, take, drop, flatMap, find, some, every, reduce, forEach, toArray.
One gotcha: iterators are single-use. Once consumed, they're done — like generators. If you need the result twice, call .toArray() once and reuse the array.
Support is broad now: Chrome 121+, Firefox 115+, Safari 16.4+, Node 22+. For older targets, it's a small polyfill.
The deeper point is the same one behind every performance fix I've shipped on dashboards: don't do work you don't need. Eager array chains do work for rows nobody will ever see. Laziness isn't cleverness here — it's just not paying for what you don't use.