if/else dan switch

Percabangan dengan if, else if, dan switch beserta truthiness dalam praktik.

Daftar isi

Percabangan memilih jalur eksekusi berdasarkan kondisi yang diperiksa saat program berjalan. Topik ini membahas rantai if, else if, dan else untuk keputusan bertingkat, aturan truthiness yang menentukan kapan sebuah nilai dianggap benar, serta switch untuk membandingkan satu ekspresi dengan banyak nilai tetap. Semua contoh dijalankan dengan Node.js, sehingga keluarannya dapat diulang persis di terminal.

if, else if, dan else#

Pernyataan if mengeksekusi sebuah blok hanya bila kondisinya bernilai benar. Kondisi ditulis di dalam tanda kurung, sedangkan blok perintahnya ditulis di dalam kurung kurawal. Bila kondisi tidak terpenuhi, blok itu dilewati dan program berlanjut ke perintah berikutnya. Bentuk else menampung jalur ketika seluruh kondisi di atasnya gagal, sedangkan else if menyisipkan pemeriksaan tambahan di antara if dan else.

Saat rantai if dijalankan, kondisi diperiksa satu per satu dari atas ke bawah, dan pemeriksaan berhenti pada kondisi pertama yang benar. Setelah cabang yang cocok menjalankan badannya, seluruh cabang di bawahnya tidak diperiksa lagi. Alur itu terlihat pada diagram berikut, yang memetakan nilai ujian 86 ke predikatnya.

if (nilai >= 90)benarPredikat Asalahelse if (nilai >= 80)benarPredikat BsalahelsebenarBelum lulus
Alur rantai if, else if, dan else untuk nilai ujian, dari kondisi paling ketat hingga cabang else

Rantai yang sama dituliskan sebagai berkas utuh di bawah ini. Berkasnya sengaja memuat dua versi, yaitu rantai yang benar dan rantai yang keliru urutan kondisinya, agar perbedaan hasilnya terlihat langsung. Jalankan berkasnya dengan node predikat-nilai.js untuk mengulang keluarannya.

js predikat-nilai.js
// Urutan kondisi menentukan hasil: rantai yang benar dan yang keliru
const nilai = 86;

// rantai yang benar: kondisi paling ketat ditempatkan di atas
if (nilai >= 90) {
  console.log("benar  -> Predikat A");
} else if (nilai >= 80) {
  console.log("benar  -> Predikat B");
} else if (nilai >= 70) {
  console.log("benar  -> Predikat C");
} else {
  console.log("benar  -> Belum lulus");
}

// rantai yang keliru: kondisi longgar ditempatkan lebih dulu
if (nilai >= 70) {
  console.log("keliru -> Predikat C");
} else if (nilai >= 80) {
  console.log("keliru -> Predikat B"); // tidak pernah tercapai
} else if (nilai >= 90) {
  console.log("keliru -> Predikat A"); // tidak pernah tercapai
} else {
  console.log("keliru -> Belum lulus");
}
text Keluaran
benar  -> Predikat B
keliru -> Predikat C

Pada keluaran, nilai 86 mendarat di Predikat B pada rantai pertama karena pemeriksaan >= 90 gagal sebelum >= 80 benar. Rantai kedua langsung menjawab Predikat C karena kondisi >= 70 diperiksa lebih dulu dan memang benar. Dua cabang di bawahnya tidak pernah sempat dievaluasi, sehingga urutan penulisan kondisi adalah bagian dari logika program, bukan sekadar gaya. Aturan praktisnya, letakkan kondisi paling ketat di atas, lalu longgarkan ke bawah.

Truthiness dalam praktik#

JavaScript tidak menuntut kondisi berupa perbandingan yang eksplisit. Nilai yang diuji if mengalami penilaian truthiness, yakni kecenderungan sebuah nilai diperlakukan sebagai benar atau salah. Nilai yang dianggap benar disebut truthy, sedangkan yang dianggap salah disebut falsy. Daftar nilai falsy pada JavaScript pendek dan tetap, sedangkan sisanya, termasuk array kosong dan string berisi karakter apa pun, selalu dianggap truthy.

NilaiPenilaian if
false, 0, -0, 0nfalsy
"" (string kosong)falsy
null, undefined, NaNfalsy
[], {}, "0", "false"truthy

Tiga nilai pada tabel itu diuji langsung oleh potongan berikut. Kasus string perlu perhatian khusus karena string kosong dan string berisi nol sering dikira sama. Angka nol disertakan sebagai pembanding karena nilainya sah tetapi dianggap salah.

js Contoh: menguji 0, string kosong, dan string berisi nol
const nol = 0;

if (nol) {
  console.log("0 -> dianggap benar");
} else {
  console.log("0 -> dianggap salah");
}

const kosong = "";
if (kosong) {
  console.log("\"\" -> dianggap benar");
} else {
  console.log("\"\" -> dianggap salah");
}

const teksNol = "0";
if (teksNol) {
  console.log("\"0\" -> dianggap benar");
} else {
  console.log("\"0\" -> dianggap salah");
}
text Keluaran
0 -> dianggap salah
"" -> dianggap salah
"0" -> dianggap benar

String kosong dianggap falsy karena tidak memuat karakter apa pun, sedangkan "0" adalah string berisi satu karakter sehingga dianggap truthy. Perbedaan ini penting saat membaca masukan, karena angka yang datang sebagai teks tidak berperilaku sama dengan angka sungguhan. Cara paling aman menghadapi nilai yang mungkin kosong adalah membandingkannya secara eksplisit, seperti pengecekan kolom nama berikut.

js Contoh: if tanpa else untuk pengecekan awal
const nama = "";

if (nama === "") {
  console.log("Nama belum diisi");
}

console.log("Lanjut memproses data");
text Keluaran
Nama belum diisi
Lanjut memproses data

Nilai null dan undefined menandai ketiadaan data dan keduanya masuk daftar falsy. Masalah muncul ketika 0 dan string kosong justru merupakan nilai yang sah, misalnya catatan tanpa panggilan sama sekali. Bila ketiga keadaan itu perlu dibedakan, uji null dan undefined secara eksplisit seperti pada contoh berikut.

js Contoh: membedakan null dan undefined dari nilai falsy lain
const namaPanggilan = null;

if (namaPanggilan === null || namaPanggilan === undefined) {
  console.log("(belum diisi)");
} else {
  console.log(namaPanggilan);
}
text Keluaran
(belum diisi)

Pola yang sama disediakan JavaScript dalam satu baris lewat operator ?? (nullish coalescing). Operator ini mengambil nilai kiri bila kiri bukan null dan bukan undefined, dan beralih ke nilai kanan bila kiri kosong. Namanya merujuk pada pasangan null dan undefined, satu-satunya keadaan yang membuatnya bergeser.

js Contoh: nilai cadangan dengan ??
const diminta = undefined;

// ?? mengambil nilai kiri bila kiri bukan null/undefined, sisanya pakai nilai kanan
const jumlahPerHalaman = diminta ?? 10;
console.log(jumlahPerHalaman);

const dimintaKedua = 24;
console.log(dimintaKedua ?? 10);
text Keluaran
10
24

Demo berikut memungkinkan pencobaan truthiness langsung. Pilih salah satu nilai pada daftar, lalu perhatikan cabang yang dijalankan if beserta tipe datanya. Nilai array kosong sengaja disertakan karena sering dikira falsy padahal termasuk truthy.

switch dengan case, break, dan default#

Pernyataan switch membandingkan satu ekspresi dengan sejumlah nilai tetap, satu nilai per case. Ketika sebuah case cocok, eksekusi berpindah ke badannya dan berjalan sampai bertemu break. Kata default menampung semua nilai yang tidak cocok dengan case mana pun, sehingga perannya mirip else pada rantai if.

js Contoh: switch untuk keterangan hari
const hari = "Rabu";
let keterangan;

switch (hari) {
  case "Sabtu":
  case "Minggu":
    keterangan = "akhir pekan";
    break;
  case "Senin":
    keterangan = "awal pekan";
    break;
  default:
    keterangan = "hari kerja";
}

console.log(`${hari} termasuk ${keterangan}`);
text Keluaran
Rabu termasuk hari kerja

Penggabungan case "Sabtu" dan case "Minggu" pada contoh di atas adalah satu badan yang dipakai bersama, pola yang dibahas lebih rinci di bawah. Rabu tidak terdaftar pada case mana pun, sehingga jalurnya jatuh ke default. Perbandingannya memakai ===, sehingga string "2" tidak akan cocok dengan angka 2.

Fallthrough yang disengaja dan yang keliru#

Fallthrough adalah perilaku switch yang melanjutkan eksekusi ke case berikutnya ketika break tidak ditulis. Perilaku ini bisa dimanfaatkan, misalnya menggabungkan beberapa case dengan badan kosong agar semuanya berbagi satu keluaran, seperti pasangan Sabtu dan Minggu pada bagian sebelumnya. Tanpa niat yang jelas, fallthrough justru menjadi sumber kekeliruan yang paling sulit dilihat. Contoh berikut memperagakan akibatnya pada penentuan bobot predikat.

js Contoh: break yang hilang pada switch
const predikat = "B";
let bobot;

switch (predikat) {
  case "A":
    bobot = 4;
  case "B":
    bobot = 3;
  case "C":
    bobot = 2;
    break;
  default:
    bobot = 0;
}

console.log(`Bobot ${predikat}: ${bobot}`);
text Keluaran
Bobot B: 2

Predikat B seharusnya berbobot 3, tetapi keluarannya 2. Setelah case "B" mengisi bobot 3, eksekusi melanjutkan ke case "C" yang menimpanya menjadi 2, dan barulah break menghentikan switch. Tidak ada pesan error yang muncul, hasilnya hanya salah tanpa suara. Karena itu banyak tim mewajibkan break di setiap case, dan penggabungan case hanya dilakukan lewat badan kosong yang memang disengaja.

Kapan switch lebih jelas daripada else if#

switch paling unggul ketika satu ekspresi dibandingkan dengan sekumpulan nilai tetap, misalnya kode menu atau hari dalam seminggu. Setiap case terbaca sebagai satu kasus yang setara. Susunan seperti itu sulit dilihat pada rantai else if yang panjang. Sebaliknya, kondisi berupa rentang seperti nilai >= 80 tidak bisa ditulis sebagai case tanpa trik, sehingga rantai if tetap menjadi pilihan yang wajar. Kondisi yang menggabungkan beberapa variabel sekaligus juga hanya mungkin ditulis dengan if.

SituasiPilihan yang cocok
Satu variabel dibandingkan dengan banyak nilai tetapswitch
Rentang nilai, misalnya >= 80 dan >= 70rantai if
Kondisi gabungan beberapa variabelrantai if
Nilai yang tidak cocok perlu jalur khususdefault atau else

Aturan praktisnya, pilih bentuk yang membuat daftar kasusnya paling mudah dibaca. Rantai if unggul saat bentuk kondisinya beragam, sedangkan switch unggul saat nilai kasusnya beragam. Keduanya menghasilkan jalur yang sama, jadi perbedaannya terletak pada kejelasan, bukan pada kemampuan.

Kesalahan umum#

  1. Mengandalkan truthiness untuk nilai yang sah berupa 0 atau string kosong. Pemeriksaan if (jumlah) menganggap jumlah 0 sama dengan ketiadaan data, padahal keduanya berbeda makna. Bedakan dengan === null, === undefined, atau ambil nilai cadangan lewat ??.
  2. Lupa break di dalam switch. Eksekusi jatuh ke case berikutnya tanpa peringatan, dan hasilnya salah secara diam-diam. Biasakan menulis break di setiap case, lalu gabungkan case hanya lewat badan kosong yang memang disengaja.
  3. Mengira truthiness menahan ReferenceError. Pengecekan if (nama) tetap memunculkan error bila variabel nama tidak pernah dideklarasikan. Periksa keberadaannya lebih dulu dengan typeof nama !== "undefined" bila variabelnya sendiri belum pasti ada.

Ringkasan#

  • Rantai if, else if, dan else memeriksa kondisi berurutan dari atas dan berhenti pada kondisi pertama yang benar, sehingga urutan kondisi menjadi bagian dari logika.
  • Daftar nilai falsy tetap dan pendek, yaitu false, 0, -0, 0n, string kosong, null, undefined, dan NaN, sedangkan nilai lain dianggap truthy dan nilai cadangan yang aman ditulis dengan ??.
  • switch membandingkan satu ekspresi dengan === terhadap sejumlah case, berhenti pada break, dan menampung sisa nilai di default.
  • break yang hilang memicu fallthrough tanpa error, sedangkan penggabungan case dengan badan kosong adalah fallthrough yang disengaja.

Referensi#