JavaScript tidak pernah berhenti berkembang — dan selama dua tahun terakhir, TC39 (komite standarisasi ECMAScript) mengangkat sejumlah proposal penting ke Stage 4, yang berarti sudah resmi masuk spesifikasi bahasa. Beberapa di antaranya menjawab masalah yang sudah lama kita hadapi: penanganan tanggal yang buruk, operasi set yang verbose, dan resource management yang rentan bocor.
Artikel ini membahas fitur-fitur ES2025 yang sudah final dan ES2026 yang dijadwalkan rilis pertengahan 2026 — bukan sekadar daftar, tapi konteks kapan dan mengapa masing-masing fitur ini relevan untuk digunakan dalam proyek nyata.
Iterator Helpers: Lazy Processing Tanpa Pre-Allocate
Sebelum ES2025, kalau kita ingin melakukan map, filter, dan take pada sebuah iterator, kita harus mengubahnya ke array terlebih dahulu. Ini berarti seluruh data dimuat ke memori — tidak ideal untuk dataset besar atau stream.
Iterator Helpers mengubah itu. Method berikut sekarang tersedia langsung pada iterator dengan evaluasi lazy (hanya memproses nilai saat dibutuhkan):
map()— transformasi per elemenfilter()— menyaring berdasarkan kondisitake(n)— ambilnelemen pertama lalu berhentidrop(n)— lewatinelemen pertamaflatMap()— flatten satu level setelah maptoArray()— realisasikan ke array saat siapforEach(),reduce(),some(),every(),find()— operasi terminal
Contoh berikut mengambil halaman pertama dari kumpulan tiket dukungan, menyaring yang prioritas tinggi, lalu mengambil tiga saja:
// support-queue.js
const ticketIterator = getTicketStream(); // returns an iterator
const urgentTickets = Iterator.from(ticketIterator)
.filter(ticket => ticket.priority === "high")
.map(ticket => ({ id: ticket.id, subject: ticket.subject }))
.take(3)
.toArray();
Tidak ada array intermediary yang dibuat. filter dan map berjalan secara lazy — nilai hanya diproses saat toArray() dipanggil, dan berhenti setelah tiga elemen ditemukan.
Iterator.from() menerima iterable apa pun — array, Set, Map, generator function, atau custom iterable. Ini pintu masuk ke semua iterator helpers.
Set Methods: Operasi Himpunan yang Lama Kita Tunggu
ES2025 akhirnya memberikan operasi himpunan matematika langsung ke objek Set. Sebelumnya, kita harus menulis sendiri atau pakai library.
Metode baru yang tersedia:
| Method | Deskripsi |
|---|---|
intersection(other) | Elemen yang ada di kedua Set |
union(other) | Semua elemen dari kedua Set |
difference(other) | Elemen di Set ini tapi tidak di other |
symmetricDifference(other) | Elemen yang ada di salah satu tapi tidak keduanya |
isSubsetOf(other) | Apakah semua elemen Set ini ada di other |
isSupersetOf(other) | Apakah other adalah subset dari Set ini |
isDisjointFrom(other) | Apakah kedua Set tidak punya elemen yang sama |
Bayangkan kita membangun fitur rekomendasi skill — kita punya skill yang dimiliki pengguna dan skill yang dibutuhkan lowongan kerja:
// skill-matcher.js
const applicantSkills = new Set(["JavaScript", "React", "CSS", "Node.js"]);
const jobRequirements = new Set(["React", "TypeScript", "Node.js", "GraphQL"]);
const matchedSkills = applicantSkills.intersection(jobRequirements);
// Set { "React", "Node.js" }
const missingSkills = jobRequirements.difference(applicantSkills);
// Set { "TypeScript", "GraphQL" }
const allMentionedSkills = applicantSkills.union(jobRequirements);
// Set { "JavaScript", "React", "CSS", "Node.js", "TypeScript", "GraphQL" }
Kode yang tadinya butuh loop manual kini jadi satu baris yang ekspresif.
Promise.try(): Error Handling yang Konsisten
Ini salah satu tambahan kecil tapi sangat membantu. Promise.try() menerima fungsi — sync maupun async — dan selalu mengembalikan Promise. Jika fungsi itu melempar error secara synchronous, error tersebut ditangkap dan diubah menjadi rejected Promise.
Tanpa Promise.try(), kita perlu membungkus kode secara manual:
// sebelumnya: kode sync yang throw tidak tertangkap di .catch()
function loadConfig(path) {
if (!path) throw new Error("path wajib diisi"); // TIDAK tertangkap di .catch()
return fetch(path).then(r => r.json());
}
loadConfig(null)
.then(config => applyConfig(config))
.catch(err => console.error(err)); // error di atas tidak masuk sini
Dengan Promise.try():
// session-loader.js
function getSessionData(sessionId) {
if (!sessionId) throw new Error("session ID tidak boleh kosong");
return fetch(`/api/sessions/${sessionId}`).then(r => r.json());
}
Promise.try(() => getSessionData(currentSessionId))
.then(data => renderDashboard(data))
.catch(err => showSessionError(err)); // semua error, sync maupun async, masuk sini
RegExp.escape(): Input Pengguna yang Aman di Regex
Setiap kali kita membuat regex dari input pengguna, kita berisiko mendapat regex injection. Karakter seperti ., *, (, ) punya makna khusus di regex dan harus di-escape manual.
RegExp.escape() melakukan itu secara otomatis:
// sebelumnya: rentan jika input mengandung karakter regex
function buildSearchPattern(query) {
return new RegExp(query, "gi"); // berbahaya jika query = "a.b*c"
}
// dengan RegExp.escape()
function buildSafePattern(query) {
return new RegExp(RegExp.escape(query), "gi");
}
const highlights = buildSafePattern("node.js (lts)");
// pattern: /node\.js \(lts\)/gi — aman
Import Attributes: Import JSON dan CSS Secara Eksplisit
ES2025 menambahkan sintaks with { type: '...' } untuk import non-JavaScript. Ini menyelesaikan masalah ambiguitas MIME type saat browser menginterpretasi file yang diimport.
// config-loader.js
import appConfig from "./app-config.json" with { type: "json" };
import themeStyles from "./theme.css" with { type: "css" };
console.log(appConfig.version); // akses langsung sebagai objek
document.adoptedStyleSheets = [themeStyles]; // gunakan CSSStyleSheet
Tanpa atribut type, beberapa runtime bisa menolak import file non-JS karena alasan keamanan. Atribut ini membuat intent eksplisit.
Temporal API: Akhir dari Penderitaan dengan Date
ES2026 membawa perubahan paling signifikan dalam sejarah penanganan waktu di JavaScript: Temporal API. Proposal ini mencapai Stage 4 pada Maret 2026 dan akan masuk spesifikasi ES2026.
Date yang kita kenal memiliki sederet masalah: mutable, tidak ada timezone yang proper, parsing inconsistent di browser berbeda, dan aritmetika tanggal yang rawan error. Temporal dirancang dari nol untuk menggantikan semua itu.
Bekerja dengan Tanggal dan Timezone
Temporal memisahkan konsep yang selama ini digabung: tanggal lokal, tanggal UTC, dan tanggal dengan timezone eksplisit.
// tanggal dengan timezone eksplisit
const meetingTime = Temporal.ZonedDateTime.from({
year: 2026,
month: 5,
day: 15,
hour: 14,
minute: 0,
timeZone: "Asia/Makassar",
});
// konversi ke timezone lain
const londonTime = meetingTime.withTimeZone("Europe/London");
console.log(londonTime.toString());
// 2026-05-15T08:00:00+01:00[Europe/London]
Aritmetika Tanggal yang Benar
Salah satu gotcha paling terkenal di Date: menambahkan satu bulan ke 31 Januari menghasilkan 2 Maret (atau 3 Maret di leap year). Temporal menangani ini dengan benar:
// deadline tracking
const projectStart = Temporal.PlainDate.from("2026-01-31");
const firstReview = projectStart.add({ months: 1 });
console.log(firstReview.toString()); // 2026-02-28 ✅ bukan 2026-03-03
const duration = Temporal.PlainDate.from("2026-04-01")
.since(projectStart);
console.log(`${duration.days} hari sejak kickoff`); // 59 hari sejak kickoff
Timestamp yang Tidak Ambigu
Untuk kebutuhan logging atau penyimpanan yang butuh presisi tinggi, Temporal.Instant bekerja di level nanosecond:
// audit-logger.js
const eventTimestamp = Temporal.Now.instant();
console.log(eventTimestamp.toString());
// 2026-04-07T07:00:00.123456789Z
// selisih waktu antara dua event
const processingTime = endEvent.since(startEvent);
console.log(`Diproses dalam ${processingTime.milliseconds}ms`);
Dukungan native Temporal baru tersedia di Chrome 144+ dan Firefox 139+. Untuk production yang butuh dukungan browser lebih luas, gunakan polyfill @js-temporal/polyfill yang sudah production-ready.
Explicit Resource Management: Tidak Ada Resource yang Terlupa
ES2026 memperkenalkan keyword using dan await using — mekanisme resource management yang mirip dengan with di Python atau using di C#. Ketika scope berakhir, resource otomatis di-dispose.
// Implementasi custom disposable
class DatabaseConnection {
constructor(url) {
this.conn = openConnection(url);
console.log("koneksi dibuka");
}
async query(sql) {
return this.conn.execute(sql);
}
async [Symbol.asyncDispose]() {
await this.conn.close();
console.log("koneksi ditutup");
}
}
// penggunaan dengan await using
async function getActiveUsers() {
await using db = new DatabaseConnection("postgres://localhost/myapp");
const rows = await db.query("SELECT id, name FROM users WHERE active = true");
return rows;
// db.close() dipanggil otomatis di sini, bahkan jika terjadi error
}
Ini menghilangkan pola try/finally yang verbose dan risiko lupa menutup koneksi saat ada early return.
Array.fromAsync(): Konsumsi Async Iterable yang Bersih
Array.fromAsync() adalah versi async dari Array.from(). Ia menerima async iterable atau sync iterable dengan nilai Promise, lalu menunggu setiap nilai sebelum memasukkannya ke array.
// pagination-fetcher.js
async function* fetchAllPages(endpoint) {
let cursor = null;
do {
const response = await fetch(`${endpoint}?cursor=${cursor ?? ""}`);
const { data, nextCursor } = await response.json();
yield* data;
cursor = nextCursor;
} while (cursor);
}
// sebelumnya: perlu loop manual
const allArticles = await Array.fromAsync(fetchAllPages("/api/articles"));
console.log(`${allArticles.length} artikel ditemukan`);
Error.isError(): Cek Error Lintas Realm
Error.isError() mungkin terlihat sepele, tapi ia menyelesaikan masalah nyata: instanceof Error tidak bekerja ketika objek Error berasal dari frame atau realm berbeda (misalnya iframe, Worker, atau vm module di Node.js).
// error-handler.js
function handleWorkerMessage(event) {
const { result, error } = event.data;
// instanceof bisa gagal jika Error dari Worker realm berbeda
if (Error.isError(error)) {
reportToMonitoring(error);
return;
}
processResult(result);
}
Hal yang Perlu Diperhatikan
Tidak semua fitur ini siap production di semua environment hari ini. Ada beberapa hal yang perlu diperhatikan sebelum mengadopsi:
- Iterator Helpers sudah tersedia di Chrome 122+, Firefox 131+, Safari 17.4+, dan Node.js 22+. Aman digunakan tanpa polyfill di project modern.
- Set Methods tersedia di semua browser modern (Chrome 122+, Firefox 127+, Safari 17+) dan Node.js 22+.
- Temporal API membutuhkan polyfill untuk browser lama. Gunakan
@js-temporal/polyfilluntuk production. usingdanawait usingsudah didukung TypeScript 5.2+ dan membutuhkan targetES2022atau lebih tinggi ditsconfig.json. Dukungan native runtime masih berkembang.Promise.try()danRegExp.escape()tersedia di Chrome 134+, Firefox 134+, dan Node.js 24+.
Kesimpulan
ES2025 dan ES2026 membawa JavaScript ke titik di mana banyak kebutuhan yang sebelumnya bergantung pada library pihak ketiga kini terpenuhi natively: date handling yang benar, set operations, resource cleanup otomatis, dan iterator yang benar-benar lazy. Adopsi bertahap adalah pendekatan yang masuk akal — mulai dari fitur dengan dukungan browser paling luas seperti Set Methods dan Iterator Helpers, sementara Temporal dan using bisa dijajal di project dengan kontrol penuh atas environment. Untuk memperluas pemahaman tentang ekosistem frontend modern secara menyeluruh, artikel belajar React di 2026 bisa menjadi langkah berikutnya.







