Setelah menguasai if-else, switch, tiga jenis loop, serta break dan continue, kita memegang seluruh alat control flow JavaScript. Tantangan berikutnya bukan lagi “bagaimana membuatnya jalan”, melainkan “bagaimana menjaganya tetap mudah dibaca” — karena program nyata menggabungkan banyak keputusan sekaligus, dan keputusan yang bersarang terlalu dalam adalah sumber kebingungan paling umum dalam peninjauan kode.
Chapter ini melatih tiga kebiasaan yang menjaga kedalaman logika: meratakan kondisi bersarang dengan negasi, memetakan aturan yang rumit ke tabel keputusan, dan menyediakan pintu keluar untuk while (true). Kita menutup dengan panduan memilih struktur serta pengantar pola guard clause yang alat utamanya — return di dalam function — menunggu kita di section Functions.
Ratakan Kondisi Bersarang #
if di dalam if di dalam if masih sah secara sintaks, tetapi pembacanya harus menumpuk konteks di kepala: “sudah di dalam cabang pertama, sekarang cabang kedua, lalu cabang ketiga”. Setiap level menambah satu indentasi, dan indentasi yang dalam tanda logika yang bisa diratakan.
Strateginya: balik arah pemeriksaan. Alih-alih “jika semua syarat terpenuhi, proses”, tulis “jika ada syarat yang gagal, tangani gagalnya lebih dulu”. Berkas berikut membandingkan kedua gaya dengan data yang sama — keluarannya harus identik:
// refaktor-kondisi.js
// Meratakan kondisi bersarang menjadi versi datar, plus while(true) yang punya pintu keluar.
const usia = 20;
const sudahBayar = true;
const kontakDarurat = "0812-3456-7890";
// --- 1a. versi bersarang: if di dalam if di dalam if ---
console.log("-- versi bersarang --");
if (usia >= 17) {
if (sudahBayar) {
if (kontakDarurat !== "") {
console.log("Pendaftaran lengkap - kartu peserta dicetak");
} else {
console.log("Isi kontak darurat terlebih dahulu");
}
} else {
console.log("Selesaikan pembayaran terlebih dahulu");
}
} else {
console.log("Usia minimal 17 tahun");
}
// --- 1b. versi datar: negasi kondisi + else if, kedalaman satu level ---
console.log("-- versi datar --");
if (usia < 17) {
console.log("Usia minimal 17 tahun");
} else if (!sudahBayar) {
console.log("Selesaikan pembayaran terlebih dahulu");
} else if (kontakDarurat === "") {
console.log("Isi kontak darurat terlebih dahulu");
} else {
console.log("Pendaftaran lengkap - kartu peserta dicetak");
}
// --- 2. while(true) yang aman: selalu ada jalur keluar dengan break ---
let sisaCoba = 3;
while (true) {
if (sisaCoba === 0) {
console.log("Kuota percobaan habis - loop dihentikan oleh break");
break;
}
console.log("Sisa percobaan:", sisaCoba);
sisaCoba = sisaCoba - 1;
}
// --- 3. tabel keputusan ongkir dipetakan langsung ke kondisi berurutan ---
const belanjaSiti = 250000;
const memberSiti = false;
if (memberSiti && belanjaSiti >= 200000) {
console.log("Ongkir gratis");
} else if (belanjaSiti >= 100000) {
console.log("Ongkir Rp5000");
} else {
console.log("Ongkir Rp15000");
}Output yang Dihasilkan:
-- versi bersarang --
Pendaftaran lengkap - kartu peserta dicetak
-- versi datar --
Pendaftaran lengkap - kartu peserta dicetak
Sisa percobaan: 3
Sisa percobaan: 2
Sisa percobaan: 1
Kuota percobaan habis - loop dihentikan oleh break
Ongkir Rp5000Mari kita telaah apa yang terjadi pada baris-baris kode di atas:
- Baris 10–22 (versi bersarang): tiga
ifbertingkat dengan tiga pasangelse. Logikanya benar, tetapi blok sukses berada tiga indentasi di dalam, dan pembaca harus mengingat cabang mana yang sedang dibuka. - Baris 26–34 (versi datar): kondisi dibalik —
usia < 17,!sudahBayar,kontakDarurat === ""— lalu disusun sebagai rantaielse if. Kedalaman tetap satu level, dan setiap baris membaca seperti daftar alasan penolakan yang berurutan. - Baris 13 dan 33 (
console.log("Pendaftaran lengkap ...")): kedua versi mencetak pesan yang sama persis untuk data yang sama. Persamaan keluaran inilah bukti bahwa perataan tidak mengubah logika — sesuatu yang wajib dicek setiap kali kita menyusun ulang kode. - Baris 38–45 (loop
while (true)): header loop memang tanpa kondisi berhenti, tetapiif (sisaCoba === 0) ... break;di dalamnya menjadi pintu keluar. Loop mencetakSisa percobaantiga kali, lalu berhenti dengan pesan kuota habis. - Baris 50–55 (pemetaan tabel ongkir): urutan kondisi mengikuti urutan baris tabel keputusan di bagian berikutnya — baris pertama tabel menjadi
ifpertama, dan seterusnya.
Ubah Aturan Jadi Tabel Keputusan Dulu #
Aturan bisnis yang melibatkan beberapa syarat mudah salah diterjemahkan langsung ke kode. Kebiasaan yang membantu: tulis dulu semua kombinasi dan hasilnya dalam tabel, lalu petakan tiap baris tabel ke satu kondisi — urutannya dipertahankan.
Aturan ongkir sebuah toko:
| Status member | Total belanja | Ongkir |
|---|---|---|
| Ya | >= 200000 | Gratis |
| Tidak | >= 100000 | Rp5000 |
| Tidak | < 100000 | Rp15000 |
Kode pada bagian 3 berkas contoh memetakan tabel itu baris per baris: gabungan memberSiti && belanjaSiti >= 200000 untuk baris pertama, lalu dua cabang berikutnya untuk sisanya. Data belanjaSiti sebesar 250000 dengan status bukan member jatuh ke baris kedua, sehingga keluarannya Ongkir Rp5000. Bila aturan berubah, tabel diperbarui lebih dulu — perubahan kodenya tinggal mengikuti baris yang berubah.
while(true) Wajib Punya Pintu Keluar #
Header while (true) sah dan kadang berguna — misalnya bila kondisi berhenti baru diketahui di tengah blok, seperti kuota percobaan pada berkas contoh. Aturannya satu: pastikan ada jalur yang pasti mencapai break atau mengubah kondisi. Loop tanpa jalur keluar membuat program berhenti merespons, dan penyebab paling sering adalah kondisi yang seharusnya diperbarui tetapi tidak.
Bila kondisi berhenti sudah diketahui sejak awal, tulis langsung di header: while (sisaCoba > 0) lebih mudah dipindai daripada while (true) plus break di dalam. Simpan pola while (true) untuk kasus yang memang tidak punya pilihan lain.
Pilih Struktur Sesuai Bentuk Keputusannya #
Semua struktur yang kita pelajari bisa saling menggantikan secara teknis, tetapi masing-masing paling jelas untuk bentuk masalah tertentu:
| Bentuk keputusan | Struktur yang pas |
|---|---|
| Satu syarat, dua jalur tindakan | if / else |
| Rentang nilai atau gabungan syarat | if / else if / else |
| Satu nilai dicocokkan ke daftar kemungkinan pasti | switch + break |
| Jumlah putaran diketahui atau bisa dihitung | for |
| Ulangi selama kondisi terpenuhi, jumlah tak pasti | while |
| Blok wajib berjalan minimal satu kali | do-while |
| Hentikan atau lewati dari dalam blok | break / continue |
| Beberapa putaran yang saling terkait | nested loops |
Daftar ini bukan aturan baku, melainkan titik mulai: bila pilihan terasa canggung, kemungkinan besar bentuk keputusannya tidak cocok dengan struktur yang dipakai.
Menuju Functions: Guard Clause dan Early Return #
Gaya “tangani kegagalan lebih dulu” yang kita pakai untuk meratakan kondisi punya nama: guard clause. Versi paling lengkapnya menulis tiap pemeriksaan sebagai blok singkat yang langsung mengakhiri alur — pola yang disebut early return:
jika usia < 17:
tampilkan "Usia minimal 17 tahun" dan selesai di sini
jika pembayaran belum lunas:
tampilkan "Selesaikan pembayaran" dan selesai di sini
... logika utama berjalan tanpa bersarang ...Potongan di atas sengaja berbentuk pseudocode, bukan JavaScript: “selesai di sini” membutuhkan statement return, dan return hanya hidup di dalam function — konsep yang belum kita pelajari. Saat section Functions terbuka nanti, potongan ini berubah menjadi kode nyata: tiap guard clause menjadi satu baris if (...) return ..., dan blok utama program tetap berada di kedalaman nol.
Sampai di sini, section Control Flow tuntas: kita bisa memilih cabang, mengulang pekerjaan, mengendalikan putaran, dan menjaga alurnya tetap dangkal. Satu kebiasaan penutup yang murah tapi berdampak: bila variabel akan dipakai sebagai kondisi, beri nama yang menyatakan benar-salah — isMember, sudahBayar, stokHabis — sehingga baris if (...) membaca seperti kalimat tanya, bukan tebakan. Alat berikutnya yang menunggu adalah Functions — unit pemakaian ulang kode yang membuat logika seperti verifikasi pendaftaran di atas dapat dipakai berulang kali tanpa disalin-tempel.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
refaktor-kondisi.js
Unduh berkas// refaktor-kondisi.js
// Meratakan kondisi bersarang menjadi versi datar, plus while(true) yang punya pintu keluar.
const usia = 20;
const sudahBayar = true;
const kontakDarurat = "0812-3456-7890";
// --- 1a. versi bersarang: if di dalam if di dalam if ---
console.log("-- versi bersarang --");
if (usia >= 17) {
if (sudahBayar) {
if (kontakDarurat !== "") {
console.log("Pendaftaran lengkap - kartu peserta dicetak");
} else {
console.log("Isi kontak darurat terlebih dahulu");
}
} else {
console.log("Selesaikan pembayaran terlebih dahulu");
}
} else {
console.log("Usia minimal 17 tahun");
}
// --- 1b. versi datar: negasi kondisi + else if, kedalaman satu level ---
console.log("-- versi datar --");
if (usia < 17) {
console.log("Usia minimal 17 tahun");
} else if (!sudahBayar) {
console.log("Selesaikan pembayaran terlebih dahulu");
} else if (kontakDarurat === "") {
console.log("Isi kontak darurat terlebih dahulu");
} else {
console.log("Pendaftaran lengkap - kartu peserta dicetak");
}
// --- 2. while(true) yang aman: selalu ada jalur keluar dengan break ---
let sisaCoba = 3;
while (true) {
if (sisaCoba === 0) {
console.log("Kuota percobaan habis - loop dihentikan oleh break");
break;
}
console.log("Sisa percobaan:", sisaCoba);
sisaCoba = sisaCoba - 1;
}
// --- 3. tabel keputusan ongkir dipetakan langsung ke kondisi berurutan ---
const belanjaSiti = 250000;
const memberSiti = false;
if (memberSiti && belanjaSiti >= 200000) {
console.log("Ongkir gratis");
} else if (belanjaSiti >= 100000) {
console.log("Ongkir Rp5000");
} else {
console.log("Ongkir Rp15000");
}