Dua regex yang pattern-nya sama persis bisa berperilaku berbeda. Yang satu berhenti pada kecocokan pertama, yang lain mengumpulkan semuanya; yang satu peduli huruf kapital, yang lain tidak. Pengatur perilaku itu disebut flag: huruf tambahan yang ditulis setelah garis miring penutup. /kopi/ dan /kopi/g adalah dua regex object dengan karakter pattern yang sama tetapi aturan kerja yang berbeda.

FlagNamaEfek
gglobalMencari semua kecocokan, bukan berhenti di yang pertama
iignore caseTidak peduli huruf besar-kecil
mmultiline^ dan $ berlaku pada tiap baris
sdotAllTitik . ikut mencocokkan baris baru
uunicodePattern membaca satu code point secara utuh
ystickyHanya mencocokkan tepat di posisi lastIndex

Flag juga dapat digabung: /kopi/gi sekaligus mencari semua kecocokan tanpa memedulikan kapitalisasi. Kita mulai dari flag yang paling sering dipakai sekaligus paling sering mengejutkan: g.

Flag g dan Properti lastIndex #

Aturan flag g: regex tidak berhenti pada kecocokan pertama. Konsekuensinya, method exec() yang biasa mengulang jawaban yang sama kini bergerak maju — setiap pemanggilan memulai pencarian dari posisi yang tersimpan di properti lastIndex milik regex object, lalu memperbarainya setelah selesai.

Berkas berikut memanggil exec() berulang kali pada regex yang sama dan mencetak posisi kecocokan beserta lastIndex-nya:

js uji-flag.js
// uji-flag.js
// Mengamati bagaimana flag g menggerakkan properti lastIndex.

const log = "stok kopi, stok teh, stok gula";
const pola = /stok/g;

// 1. Setiap exec mulai mencari dari posisi lastIndex
let hasil = pola.exec(log);
console.log(hasil[0], "indeks", hasil.index, "| lastIndex", pola.lastIndex);
hasil = pola.exec(log);
console.log(hasil[0], "indeks", hasil.index, "| lastIndex", pola.lastIndex);
hasil = pola.exec(log);
console.log(hasil[0], "indeks", hasil.index, "| lastIndex", pola.lastIndex);

// 2. Kehabisan kecocokan: exec mengembalikan null, lastIndex kembali ke 0
hasil = pola.exec(log);
console.log(hasil);
console.log(pola.lastIndex);

// 3. Loop while: pola idiomatik membaca semua kecocokan
const polaLanjut = /stok/g;
let temuan;
while ((temuan = polaLanjut.exec(log)) !== null) {
  console.log(temuan[0], "di indeks", temuan.index);
}
console.log(temuan, polaLanjut.lastIndex);

Output yang Dihasilkan:

text
stok indeks 0 | lastIndex 4
stok indeks 11 | lastIndex 15
stok indeks 21 | lastIndex 25
null
0
stok di indeks 0
stok di indeks 11
stok di indeks 21
null 0

Jalankan dengan node uji-flag.js dan cocokkan hasilnya. Mari kita telaah baris-baris pentingnya:

  1. Baris 8 (pola.exec(log)): kecocokan pertama “stok” ditemukan pada indeks 0, dan lastIndex melompat ke 4 — tepat setelah kata tersebut.
  2. Baris 10 dan 12: dua pemanggilan berikutnya tidak mulai dari awal; keduanya meneruskan dari lastIndex dan menemukan kecocokan di indeks 11 dan 21.
  3. Baris 16–18: kehabisan kecocokan membuat exec() mengembalikan null, lalu lastIndex otomatis kembali ke 0 — regex siap memulai dari awal lagi.
  4. Baris 23 (while ((temuan = polaLanjut.exec(log)) !== null)): bentuk idiomatik membaca semua kecocokan; hasil assignment dipakai sebagai kondisi, sehingga loop berhenti tepat saat exec() mengembalikan null.
  5. Baris 26: bukti penutup — setelah loop selesai, temuan bernilai null dan lastIndex kembali 0.

Cara yang lebih ringkas untuk mengumpulkan semua kecocokan adalah match dengan flag g atau matchAll dari chapter Searching Strings. Perbedaannya: keduanya mengumpulkan hasil sekaligus tanpa menyimpan posisi di antara pemanggilan, sehingga tidak menimbulkan efek lastIndex.

Flag i: Mengabaikan Huruf Besar-Kecil #

Flag i memerintahkan pencarian tanpa memedulikan kapitalisasi — tebalik dari perilaku bawaan yang peka huruf:

js
console.log(/budi/.test("Datang ke acara Budi"));
console.log(/budi/i.test("Datang ke acara Budi"));
console.log("Budi dan budi".match(/budi/gi));

Output yang Dihasilkan:

text
false
true
[ 'Budi', 'budi' ]

Tanpa i, kata “Budi” kapital tidak cocok dengan pattern /budi/. Dengan i, keduanya cocok — dan baris ketiga memperlihatkan penggabungan dua flag: g mengumpulkan semua kecocokan, i menyamakan perlakuan huruf.

Dua hal perlu diingat tentang flag i. Pertama, ia berlaku untuk seluruh pattern, bukan sebagian — tidak ada cara memilih satu huruf saja yang boleh kapital melalui flag; bila kebutuhannya seperti itu, daftarkan pilihannya di dalam character class, misalnya [Bb]udi. Kedua, efeknya paling terasa pada data yang ditulis manusia — nama, judul, dan isi pesan — karena kapitalisasi di sana tidak pernah seragam.

Flag m dan s: Baris Baru #

String boleh memuat banyak baris, dan teks seperti itu menimbulkan dua pertanyaan: di mana batas “awal string”? dan apakah titik . menjangkaunya? Flag m menjawab yang pertama — ^ dan $ berlaku pada awal dan akhir tiap baris, bukan hanya awal dan akhir string. Flag s menjawab yang kedua — titik ikut mencocokkan baris baru.

js
const daftar = "kopi: 12000\nteh: 8000\ngula: 14000";
console.log(/^teh/.test(daftar));
console.log(/^teh/m.test(daftar));

Output yang Dihasilkan:

text
false
true

Tanpa m, ^ hanya cocok di posisi nol — dan string itu dimulai dengan “kopi”, bukan “teh”. Dengan m, baris kedua yang dimulai “teh” juga dianggap awal, sehingga hasilnya true.

js
const memo = "Judul: Reunion Keluarga\nIsi: sampai jumpa";
console.log(/Judul.*Isi/.test(memo));
console.log(/Judul.*Isi/s.test(memo));

Output yang Dihasilkan:

text
false
true

Tanpa s, titik berhenti di garis batas baris baru sehingga .* tidak mampu menjangkau dari “Judul” sampai “Isi”. Dengan s, kedua kata itu terhubung meskipun berada di baris berbeda.

Flag u: Satu Code Point #

JavaScript menyimpan string sebagai rangkaian code unit UTF-16. Karakter Latin biasa menempati satu code unit, tetapi banyak karakter non-Latin — emoji misalnya — menempati dua. Tanpa flag u, elemen pattern seperti titik hanya mencocokkan satu code unit; dengan u, pattern membaca satu code point secara utuh.

Flag u juga mengubah cara pattern membaca escape di atas satu code unit, sehingga bila data kita memuat karakter non-Latin dan perilaku pencariannya terasa tidak konsisten, flag ini yang pertama dicoba.

js
console.log(/^.$/.test("👍"));
console.log(/^.$/u.test("👍"));

Output yang Dihasilkan:

text
false
true

Emoji itu tersimpan sebagai dua code unit, sehingga /^.$/ tanpa u gagal — titik hanya melihat setengah karakter. Dengan u, regex menghitungnya sebagai satu karakter utuh dan pola cocok.

Flag y: Hanya di Posisi lastIndex #

Flag y (sticky) menuntut kecocokan dimulai tepat di posisi lastIndex — regex tidak boleh memindai maju mencari kecocokan di posisi lain. Ia mirip flag g dalam hal memakai lastIndex, tetapi jauh lebih ketat:

js
const polaLengket = /[0-9]+/y;
polaLengket.lastIndex = 3;
console.log(polaLengket.exec("abc123")[0]);
polaLengket.lastIndex = 2;
console.log(polaLengket.exec("abc123"));

Output yang Dihasilkan:

text
123
null

Saat lastIndex bernilai 3, regex menemukan "123" persis di posisi itu. Saat lastIndex digeser ke 2, karakter pada posisi itu adalah huruf c — dan sticky menolak memindai maju ke angka, sehingga hasilnya null.

Jika dibandingkan berdampingan: flag g mengizinkan exec melompat dari satu kecocokan ke berikutnya, sedangkan flag y menuntut kecocokan berada tepat di tempat yang ditunjuk lastIndex. Keduanya sama-sama menyimpan posisi; yang berbeda adalah seberapa longgar kecocokan boleh dicari.

Enam flag kini sudah lengkap: g mengumpulkan semua kecocokan, i menyamakan huruf, m dan s mengurus baris baru, u membaca code point utuh, dan y menahan pencarian pada satu posisi. Dengan pattern dari chapter sebelumnya dan flag dari chapter ini, kita siap memakai regex untuk tugas paling praktis: memvalidasi format input.

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

uji-flag.js

Unduh berkas
javascript
// uji-flag.js
// Mengamati bagaimana flag g menggerakkan properti lastIndex.

const log = "stok kopi, stok teh, stok gula";
const pola = /stok/g;

// 1. Setiap exec mulai mencari dari posisi lastIndex
let hasil = pola.exec(log);
console.log(hasil[0], "indeks", hasil.index, "| lastIndex", pola.lastIndex);
hasil = pola.exec(log);
console.log(hasil[0], "indeks", hasil.index, "| lastIndex", pola.lastIndex);
hasil = pola.exec(log);
console.log(hasil[0], "indeks", hasil.index, "| lastIndex", pola.lastIndex);

// 2. Kehabisan kecocokan: exec mengembalikan null, lastIndex kembali ke 0
hasil = pola.exec(log);
console.log(hasil);
console.log(pola.lastIndex);

// 3. Loop while: pola idiomatik membaca semua kecocokan
const polaLanjut = /stok/g;
let temuan;
while ((temuan = polaLanjut.exec(log)) !== null) {
  console.log(temuan[0], "di indeks", temuan.index);
}
console.log(temuan, polaLanjut.lastIndex);