JavaScript Iterator Helpers (ES2025): Lazy map/filter/take

Foto oleh luis gomes on Pexels
Iterator helpers adalah metode seperti map, filter, take, drop, flatMap, reduce, dan toArray yang ditambahkan langsung ke prototype iterator di ES2025. Mereka memungkinkan Anda mengubah dan mengonsumsi iterator apa pun (array lewat values(), generator, Map, Set) tanpa menyebarnya menjadi array dulu. Metode producer bersifat lazy, jadi tak ada array perantara yang dialokasikan.
Metode array bersifat eager: filter, map, dan slice masing-masing membangun array baru penuh, jadi satu rangkaian mengalokasikan beberapa array sekali pakai. Iterator helpers bersifat lazy: setiap nilai ditarik melewati seluruh rangkaian satu per satu tanpa perantara. Itu menghemat memori pada data besar dan membuat take bisa short-circuit rangkaian setelah beberapa hasil saja.
Ya. Proposal TC39 mencapai Stage 4 pada plenari Oktober 2024 dan dirilis di ES2025. MDN menandainya Baseline Newly available sejak Maret 2025. Fitur ini bekerja di Chrome dan Edge 122 (V8 v12.2), Firefox 131, Safari 18.4, Node.js 22 LTS dan 24, Bun 1.1.31+, serta Deno 2.
Ya, itu keunggulan utamanya. Karena producer lazy hanya menarik nilai sesuai kebutuhan, Anda bisa merangkai map atau filter di atas generator tak hingga dan membatasinya dengan take. Metode array tak bisa, karena akan mencoba mewujudkan array tanpa akhir dan menggantung. Hanya hindari consumer eager seperti reduce pada sumber tak terbatas tanpa take di depannya.
Lewati untuk array kecil yang akan Anda konsumsi penuh: metode array sangat dioptimalkan JIT, sementara protokol iterator menambah overhead per nilai yang sering membuat rangkaian lazy lebih lambat di bawah beberapa ribu item. Hindari juga jika Anda butuh indeks, length, pemakaian ulang, atau menelusuri data yang sama dua kali, karena iterator itu sekali jalan dan sekali pakai.

Foto oleh luis gomes on Pexels
Ringkasan Utama
Iterator helpers JavaScript, distandarkan di ES2025, menambahkan map, filter, take, drop, flatMap yang lazy plus consumer seperti reduce dan toArray langsung ke iterator. Karena setiap nilai ditarik sesuai kebutuhan, rangkaian tidak mengalokasikan array perantara dan bisa short-circuit atau berjalan di atas urutan tak hingga — hal yang tak bisa dilakukan metode array.
Bertahun-tahun saya merangkai metode array tanpa memikirkan biayanya. Memanggil filter lalu map lalu slice memang rapi dibaca, tetapi setiap langkah dalam rangkaian itu membangun array baru di memori, bahkan ketika saya hanya butuh beberapa hasil pertama. Pada array kecil tak ada yang sadar. Pada ekspor sejuta baris, atau stream yang tak pernah berakhir, pola itu ambruk.
ES2025 menutup celah itu dengan menaruh metode familiar yang sama pada iterator itu sendiri, tempat mereka berjalan secara lazy. Di tulisan ini saya membahas apa itu iterator helpers, bagaimana lazy evaluation berbeda dari array chaining yang eager, status standardisasi dan dukungan runtime persis yang saya verifikasi terhadap sumber primer, serta kasus-kasus di mana memilih versi lazy justru keliru.
Iterator helpers adalah metode yang ditambahkan ke prototype yang dibagikan oleh setiap iterator bawaan — objek yang Anda dapatkan dari array lewat values, dari Map atau Set, dari generator, atau dari NodeList di DOM. Sebelum ES2025 metode itu hanya ada di array, jadi langkah lazim adalah menyebar iterator menjadi array dulu hanya untuk memanggil map. Kini metode itu ada langsung di iterator, dan terbagi menjadi dua keluarga.
Perubahan tunggal itu menghapus sebagian besar alasan saya dulu menyebar iterator menjadi array. Rangkaiannya terbaca hampir sama, tetapi model eksekusi di baliknya benar-benar berbeda.
Perbedaannya ada pada di mana pekerjaan terjadi dan berapa biaya memorinya. Metode array bersifat eager: filter menelusuri seluruh array dan mengembalikan array penuh, lalu map menelusurinya dan mengembalikan array penuh lagi, dan barulah slice mengambil potongan yang Anda mau. Iterator helpers bersifat lazy: setiap nilai ditarik melewati seluruh rangkaian satu per satu, sehingga tak pernah ada array perantara yang dibangun.
// Eager: array chaining allocates a full array at every step
const firstThree = numbers
.filter((n) => n % 2 === 0) // new array of every even number
.map((n) => n * n) // new array of every square
.slice(0, 3); // then throw almost all of it away
// Lazy: iterator helpers pull one value at a time, no intermediates
const firstThreeLazy = numbers
.values() // an Iterator over the array
.filter((n) => n % 2 === 0)
.map((n) => n * n)
.take(3) // stop after 3 values are produced
.toArray(); // [0, 4, 16]
// Works on an infinite source — arrays cannot do this at all
function* naturals() {
let i = 0;
while (true) yield i++;
}
const firstFiveSquares = naturals()
.map((n) => n * n)
.take(5)
.toArray(); // [0, 1, 4, 9, 16]Perhatikan pemanggilan take di versi lazy. Karena take berhenti meminta nilai begitu punya tiga, filter dan map di atasnya hanya berjalan untuk segelintir item yang dibutuhkan guna menghasilkan tiga hasil itu — bukan untuk seluruh sumber. Short-circuit itulah yang membuat rangkaian lazy sanggup berjalan di atas generator tak hingga di bawah: metode array akan mencoba mewujudkan array tanpa akhir dan menggantung selamanya.
Array itu iterable tetapi bukan iterator, jadi metode helper tidak ada langsung padanya. Panggil values pada array dulu untuk mendapat iterator, lalu rangkai. Generator, iterator Map dan Set, serta iterator NodeList sudah berupa iterator, jadi Anda bisa langsung merangkainya.
Ini standar yang sudah dirilis, bukan proposal yang masih berjalan. Proposal iterator helpers TC39 mencapai Stage 4 pada plenari Oktober 2024 dan digabungkan ke ECMA-262 sebagai bagian ES2025. MDN mencantumkan fitur ini sebagai Baseline Newly available sejak Maret 2025, artinya setiap mesin browser besar terkini mendukungnya. Versi konkret yang saya konfirmasi:
Satu catatan penting: padanan asinkronnya — helper yang sama pada AsyncIterator untuk stream dan async generator — adalah proposal TC39 terpisah yang masih bergerak melalui proses, jadi hanya helper sinkron yang menjadi bagian ES2025 saat ini. Jika Anda harus mendukung runtime lama, polyfill core-js dan paket es-iterator-helpers menutupinya.
Ketika memutuskan di antara keduanya, inilah tabel mental yang saya telusuri. Bukan soal salah satu selalu benar — melainkan keduanya mengoptimalkan bentuk data yang berbeda.
| Aspek | Metode array (eager) | Iterator helpers (lazy) |
|---|---|---|
| Data perantara | Array penuh dialokasikan di setiap langkah | Satu nilai per saat, tanpa perantara |
| Short-circuit dengan take | Menjalankan seluruh rangkaian, lalu memotong | Berhenti begitu take terpenuhi |
| Sumber tak hingga atau stream | Mustahil — array tak pernah selesai | Kelas satu, selama Anda membatasinya |
| Pemakaian ulang dan akses acak | Array bisa dipakai ulang dan diindeks | Sekali jalan dan habis setelah dikonsumsi |
| Paling cocok | Array kecil di memori | Data besar, banyak difilter, atau tak terbatas |
Lazy bukan peningkatan gratis. Untuk array kecil metode eager biasanya menang, karena mesin sangat mengoptimalkan iterasi array sementara setiap langkah rangkaian iterator membayar biaya protokol iterator — sebuah pemanggilan metode dan objek hasil per nilai. Di bawah beberapa ribu item, overhead per nilai itu sering membuat rangkaian lazy terukur lebih lambat, dan selalu lebih sulit dibaca untuk transformasi dua langkah sederhana yang toh akan Anda wujudkan penuh.
Ingat metode mana yang consumer eager. reduce tidak lazy — ia harus mengunjungi setiap nilai, jadi memanggilnya pada iterator tak hingga tak akan pernah kembali. Dan iterator itu sekali pakai: begitu rangkaian helper mengonsumsinya, iterasi lagi tak menghasilkan apa-apa. Jika Anda butuh datanya dua kali, atau butuh length dan indeks, tetaplah dengan array.
Jadi anti-pola-nya jelas: jangan pakai iterator helpers pada array kecil yang akan Anda konsumsi penuh, jangan panggil reduce atau toArray pada sumber tak terbatas tanpa take di depannya, dan jangan berharap menelusuri iterator yang sama dua kali.
Aturan praktis saya sederhana. Jika datanya besar, banyak difilter, di-stream, atau tak hingga — apalagi jika saya hanya butuh beberapa hasil pertama — saya pakai iterator helpers dan biarkan laziness melewati pekerjaan. Jika itu array sedang yang toh akan saya ubah kembali menjadi array, saya tetap dengan metode array eager. Sintaksnya nyaris identik, jadi berpindah nanti pun murah; kemenangannya ada pada memilih model evaluasi yang cocok dengan datanya.