menengahfungsirekursiMenengah3 mnt baca

Rekursi: Fungsi yang Memanggil Dirinya Sendiri

Memahami rekursi: fungsi yang memanggil dirinya sendiri, kenapa base case itu wajib, dan cara menelusuri struktur data bertingkat seperti komentar berbalas.

Kenapa Rekursi Ada

Beberapa masalah punya bentuk yang "mirip dengan dirinya sendiri". Faktorial: 4! = 4 x 3!, dan 3! = 3 x 2!. Folder berisi subfolder yang berisi subfolder lagi. Komentar punya balasan, balasan punya balasan lagi. Untuk masalah seperti ini, menulis loop biasa terasa dipaksakan, sementara fungsi yang memanggil dirinya sendiri (rekursi) membaca persis seperti definisi masalahnya.

Contoh 1: Faktorial

javascript
function faktorial(n) {
  if (n <= 1) return 1; // base case: titik berhenti
  return n * faktorial(n - 1); // langkah rekursif
}

console.log(faktorial(5)); // 120

Jalurnya seperti ini: faktorial(5) menunggu hasil faktorial(4), yang menunggu faktorial(3), terus sampai faktorial(1) yang langsung mengembalikan 1. Lalu hasilnya "naik" kembali: 2 x 1 = 2, 3 x 2 = 6, 4 x 6 = 24, 5 x 24 = 120.

Base Case: Rem Darurat

Setiap rekursi WAJIB punya base case, yaitu kondisi yang menghentikan pemanggilan diri sendiri. Tanpa base case, fungsi memanggil dirinya selamanya sampai JavaScript menyerah:

javascript
function rusak(n) {
  return rusak(n - 1); // tidak pernah berhenti!
}
rusak(10); // RangeError: Maximum call stack size exceeded

Bayangkan tumpukan piring: setiap pemanggilan rekursif menaruh piring baru di atas. Base case adalah momen kita mulai mengambil piring dari atas. Tanpa itu, tumpukannya roboh (stack overflow).

Contoh 2: Menelusuri Struktur Bertingkat

Ini kekuatan sejati rekursi. Contoh: komentar dengan balasan tak terbatas.

javascript
const komentar = [
  {
    teks: "Bagus!",
    balasan: [
      { teks: "Setuju", balasan: [] },
      { teks: "Makasih", balasan: [
        { teks: "Sama-sama", balasan: [] }
      ]}
    ]
  },
  { teks: "Halo", balasan: [] }
];

function hitungSemua(daftar) {
  let total = daftar.length;
  for (const k of daftar) {
    total += hitungSemua(k.balasan); // rekursi untuk tiap balasan
  }
  return total;
}

console.log(hitungSemua(komentar)); // 5

Dengan loop biasa, kamu harus tahu dulu seberapa dalam sarangnya (2 level? 10 level?). Dengan rekursi, kedalaman berapapun ditangani otomatis.

Rekursi vs Loop

Hampir semua rekursi bisa ditulis sebagai loop, dan loop biasanya lebih hemat memori. Pakai rekursi ketika strukturnya memang bertingkat atau bercabang (pohon folder, JSON bersarang, menu multi-level). Pakai loop untuk pengulangan datar yang sederhana.

Jebakan Umum

Pertama, setiap panggilan rekursif harus membuat argumennya "mendekati" base case. Kalau faktorial memanggil faktorial(n) tanpa mengurangi n, ia tidak pernah berhenti. Kedua, jangan pakai rekursi untuk puluhan ribu level kedalaman: call stack browser terbatas dan program akan crash. Ketiga, waspadai perhitungan berulang yang boros, seperti Fibonacci naif yang menghitung ulang cabang yang sama berkali-kali (solusinya: simpan hasil perhitungan atau pakai loop).

Catatan teknis: Rekursi bekerja dengan call stack, tumpukan bingkai pemanggilan fungsi. Setiap bingkai menyimpan variabel lokalnya sendiri, makanya tiap level rekursi punya nilai n yang berbeda. Inilah yang membuat pola "turun lalu naik" pada contoh faktorial bisa terjadi.

Live Playground
export default function App(): JSX.Element {
  return <h1>Hello world</h1>
}

Edit kode di kiri, preview kanan ter-update otomatis.

Tantangan

Hitung Total Balasan

Forum dan aplikasi chat nyata menyimpan komentar berbalas dengan kedalaman tak terbatas, dan kamu sering perlu menghitung total semuanya (misalnya untuk badge jumlah komentar). Buat fungsi totalKomentar(daftar) yang menerima array komentar berbentuk { teks, balasan: [...] } dan mengembalikan jumlah SEMUA komentar termasuk balasannya, sedalam apapun.

<!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>