Kondisi Bertingkat & Early Return
Menangani kondisi kompleks tanpa nesting dalam: guard clause dan early return.
Analogi: Antrean dengan Banyak Pintu Tolak
Bayangkan antrean masuk wahana. Petugas di depan memeriksa satu per satu: tidak bawa tiket, langsung disuruh ke loket (pintu keluar pertama); tinggi badan kurang, disuruh pulang (pintu keluar kedua); semua syarat lolos, baru boleh masuk wahana. Setiap penolakan ditangani cepat di depan, sehingga yang sampai ke wahana tinggal orang-orang yang valid.
Itulah guard clause: alih-alih menumpuk if di dalam if di dalam if (nesting dalam), kamu menangani setiap kasus gagal sedini mungkin lalu keluar cepat dengan return. Kode menjadi datar dan setiap aturan terlihat jelas.
Kenapa Konsep Ini Ada?
Kondisi dunia nyata jarang tunggal. "Bisa belanja" butuh pengguna login DAN akun aktif DAN saldo cukup. Kalau ditulis dengan nesting, kodenya menjorok ke kanan seperti tangga dan otak harus mengingat semua syarat yang sudah lolos untuk memahami baris terdalam. Masalah yang dipecahkan guard clause ada tiga. Pertama, keterbacaan: kode datar lebih mudah dibaca daripada piramida menjorok. Kedua, kejelasan aturan: setiap baris guard adalah satu aturan bisnis yang berdiri sendiri ("tanpa login, tidak bisa belanja"). Ketiga, perawatan: menambah atau menghapus satu syarat tidak menggeser seluruh struktur.
Pola ini disebut guard clause atau early return, dan ia adalah salah satu kebiasaan yang paling membedakan kode pemula dari kode programmer berpengalaman. Bedanya bukan kepintaran, tapi disiplin menangani kasus gagal di awal.
Contoh Kode
Contoh 1: Dari nesting neraka ke guard clause
// SUSAH DIBACA: piramida nesting
function bisaBelanjaNesting(user) {
if (user) {
if (user.aktif) {
if (user.saldo > 0) {
return "Bisa belanja";
} else {
return "Saldo habis";
}
} else {
return "Akun nonaktif";
}
} else {
return "Login dulu";
}
}
// MUDAH DIBACA: datar dengan guard clause
function bisaBelanja(user) {
if (!user) return "Login dulu";
if (!user.aktif) return "Akun nonaktif";
if (user.saldo <= 0) return "Saldo habis";
return "Bisa belanja";
}
console.log(bisaBelanja({ aktif: true, saldo: 50000 })); // "Bisa belanja"
console.log(bisaBelanja(null)); // "Login dulu"Bandingkan keduanya: versi nesting memaksamu melacak tiga level untuk tahu kenapa "Saldo habis" muncul. Versi guard clause membaca seperti daftar aturan: gagal di baris mana pun, langsung keluar dengan pesan yang jelas. Logikanya identik, bebannya di otak jauh berbeda.
Contoh 2: Validasi formulir pendaftaran yang realistis
function validasiDaftar(data) {
if (!data.nama || data.nama.length < 3) {
return "Nama minimal 3 karakter";
}
if (!data.email || !data.email.includes("@")) {
return "Email tidak valid";
}
if (!data.password || data.password.length < 8) {
return "Password minimal 8 karakter";
}
if (data.password !== data.konfirmasiPassword) {
return "Konfirmasi password tidak cocok";
}
return "Pendaftaran valid, lanjut!";
}
console.log(validasiDaftar({ nama: "Bu", email: "[email protected]", password: "12345678", konfirmasiPassword: "12345678" }));
// "Nama minimal 3 karakter"
console.log(validasiDaftar({ nama: "Budi", email: "[email protected]", password: "12345678", konfirmasiPassword: "12345678" }));
// "Pendaftaran valid, lanjut!"Inilah bentuk validasi formulir di aplikasi nyata: setiap guard memeriksa satu aturan dan mengembalikan pesan error spesifik. Tanpa pola ini, validasi empat aturan akan menjadi nesting empat level yang mengerikan. Dengan guard clause, menambah aturan baru semudah menambah satu baris di atas.
Kesalahan Umum Pemula
1. Memakai return di luar fungsi. Contoh yang salah: menulis guard clause di top-level script lalu mendapat error Illegal return statement. Yang benar: return hanya hidup di dalam fungsi. Bungkus logikamu dalam function dulu, seperti semua contoh di modul ini.
2. Guard clause yang tidak mengembalikan apa-apa. Contoh yang salah:
function cek(user) {
if (!user) return; // mengembalikan undefined, membingungkan pemanggil
return "OK";
}Yang benar: kembalikan nilai yang bermakna dan konsisten, misalnya string pesan atau object { ok: false, pesan: "..." }, agar pemanggil tahu apa yang terjadi tanpa menebak.
3. Urutan guard yang salah. Contoh yang salah: mengecek user.saldo sebelum mengecek user ada, sehingga error Cannot read properties of null. Yang benar: selalu cek dari yang paling dasar dulu (apakah user ada?) baru turun ke detailnya (apakah saldonya cukup?). Urutan guard adalah urutan logika.
4. Mencampur guard clause dengan else yang tidak perlu. Contoh yang berisik:
if (!user) {
return "Login dulu";
} else {
return "Bisa belanja";
}Yang benar: setelah return, else tidak dibutuhkan karena baris di bawahnya otomatis hanya jalan kalau guard tidak terpicu. Tulis datar saja, itulah inti pola ini.
Ringkasan
Guard clause membalik logika nesting: tangani setiap kasus gagal sedini mungkin dengan return cepat, sehingga jalur sukses tetap datar dan bersih di bawah. Pola ini membuat aturan bisnis terbaca seperti daftar periksa, memudahkan penambahan syarat baru, dan dipakai luas di validasi formulir, otorisasi, dan pengecekan prasyarat. Nesting 1-2 level masih wajar untuk logika yang memang berlapis; di atas itu, datarkan dengan guard clause.
export default function App(): JSX.Element { return <h1>Hello world</h1> }
Tantangan
Validasi Tiket
Buat fungsi cekTiket(umur, punyaTiket) dengan guard clause: umur < 5 → "Gratis (balita)"; tidak punya tiket → "Beli tiket dulu"; selain itu → "Selamat menonton". Validasi berlapis seperti ini adalah pekerjaan harian di backend dan frontend: setiap gerbang (umur, tiket, pembayaran) diperiksa satu per satu sebelum pengguna diizinkan lanjut.
<!doctype html> <html> <head> <meta charset="utf-8" /> </head> <body> <h1>Halo JS</h1> <p>Buka console preview untuk melihat output.</p> <script src="index.js"></script> </body> </html>