Alternation (Atau)
Operator pipe | berfungsi sebagai "atau" di regex. Pattern di kiri ATAU kanan harus cocok:
/kucing|anjing/.test("Saya punya kucing"); // true
/kucing|anjing/.test("Saya punya anjing"); // true
/kucing|anjing/.test("Saya punya ikan"); // false
Alternation dalam Group
Tanpa group, | memisahkan seluruh pattern. Gunakan group untuk membatasi scope alternation:
// TANPA group: "saya kucing" ATAU "anjing"
/saya kucing|anjing/.test("anjing"); // true (bukan yang diinginkan)
// DENGAN group: "saya" diikuti "kucing" ATAU "anjing"
/saya (kucing|anjing)/.test("anjing"); // false ✓
/saya (kucing|anjing)/.test("saya anjing"); // true ✓
Bisa juga lebih dari dua pilihan:
/\.(jpg|jpeg|png|gif|webp)$/i.test("foto.PNG"); // true
/\.(jpg|jpeg|png|gif|webp)$/i.test("doc.pdf"); // false
Lookahead
Lookahead memeriksa apakah suatu pattern ada di depan posisi saat ini, tanpa mengonsumsi (memasukkan) karakter tersebut ke dalam kecocokan.
Positive Lookahead (?=...)
Cocok jika pattern di depan ada:
// Temukan angka yang diikuti "px"
"width: 100px, height: 200em".match(/\d+(?=px)/g);
// ["100"] — hanya 100 yang diikuti "px"
// Harga yang diikuti "rb"
"50rb dan 100rb".match(/\d+(?=rb)/g);
// ["50", "100"]
Perhatikan bahwa "px" dan "rb" tidak termasuk dalam hasil match.
Negative Lookahead (?!...)
Cocok jika pattern di depan TIDAK ada:
// Angka yang TIDAK diikuti "px"
"100px 200em 300".match(/\d+(?!px)/g);
// ["10", "200", "300"] — (10 karena "100" split)
// Lebih presisi dengan word boundary:
"100px 200em 300".match(/\b\d+(?!px)\b/g);
// ["200", "300"]
Lookbehind
Lookbehind memeriksa apa yang ada di belakang posisi saat ini.
Positive Lookbehind (?<=...)
// Angka yang didahului "quot;
"$100 dan 200 dan $300".match(/(?<=\$)\d+/g);
// ["100", "300"]
// Teks setelah "nama: "
"nama: Budi".match(/(?<=nama: )\w+/);
// ["Budi"]
Negative Lookbehind (?<!...)
// Angka yang TIDAK didahului "quot;
"$100 dan 200 dan $300".match(/(?<!\$)\b\d+/g);
// ["200"]
Kombinasi Lookahead
Lookahead sering digunakan untuk validasi password yang membutuhkan beberapa syarat sekaligus:
// Password harus mengandung:
// - Minimal 8 karakter
// - Minimal 1 huruf besar
// - Minimal 1 angka
// - Minimal 1 karakter spesial
const passwordRegex = /^(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$/;
passwordRegex.test("abc12345"); // false (tidak ada huruf besar)
passwordRegex.test("Abc12345"); // false (tidak ada special char)
passwordRegex.test("Abc1234!"); // true ✓
Setiap (?=...) adalah syarat terpisah yang harus dipenuhi, dan semuanya diperiksa dari posisi yang sama (awal string karena ada ^).
Contoh Praktis
// Format angka dengan pemisah ribuan
const formatRibuan = (n) =>
String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ".");
console.log(formatRibuan(1234567)); // "1.234.567"
// Temukan method yang diikuti tanda kurung
const code = "getData() saveData() count";
console.log(code.match(/\w+(?=\(\))/g));
// ["getData", "saveData"]
🎭 Analogi sehari-hari: Lookahead/lookbehind = mata-mata cek depan/belakang tanpa pindah posisi. Biasa: "match ABC, lalu konsumsi". Lookahead: "match ABC kalau di depan ada XYZ, tapi gak ambil XYZ ke hasil". Mata-mata intip, gak ngambil. Berguna untuk match by context tanpa include context-nya di output.
💡 Lookahead = composable conditions: ^(?=.*[A-Z])(?=.*\d)(?=.*[!@#]).{8,}$ = password validator. Tiap (?=...) = satu kondisi, semua harus terpenuhi dari posisi awal. Cara terbersih untuk multi-condition validation tanpa parsing manual.
⚠️ Jebakan klasik:
- Lookbehind variable-length dulu gak support — sekarang JS modern ES2018+ support, tapi cek target environment
- Greedy lookahead = bisa jadi performance issue. Pakai literal kalau bisa
- Confuse
(?=...)vs(?:...)—(?=)lookahead,(?:)non-capturing group - Pakai lookahead untuk parse nested — biasanya gak bisa. Pakai parser proper
- Negation chain ambigu —
(?!a)(?!b)= tidakaDAN tidakb, bukan tidak (aataub)
🎯 Pattern lookahead populer:
- Format ribuan:
\B(?=(\d{3})+(?!\d))insert separator - Password rules:
(?=.*[A-Z])(?=.*\d)(?=.*[!@#]).{8,} - Match function name:
\w+(?=\() - After dollar:
(?<=\$)\d+ - Not in URL:
\d+(?!.*\.(jpg|png))
TL;DR: Alternation | = OR, gunakan group (a|b) untuk batasi scope. Lookahead (?=...) / lookbehind (?<=...) = match by context tanpa konsumsi karakter. Powerful untuk multi-condition validation. Lookbehind di JS perlu cek browser support.