Closures — JavaScript

Bayangin kamu pinjem buku dari perpus, terus pas keluar bawa juga catatan kecil yang kamu tulis selama baca di sana. Walaupun perpus udah tutup (function luar s

Bayangin kamu pinjem buku dari perpus, terus pas keluar bawa juga catatan kecil yang kamu tulis selama baca di sana. Walaupun perpus udah tutup (function luar selesai), kamu tetep bisa baca catatannya — karena udah ada di kantong kamu. Itu Closure di JavaScript: function dalam "kantongin" variabel dari scope luar, tetep bisa pake walaupun scope itu udah lama selesai. Konsep yang bikin pemula bingung tapi powerful banget — fondasi dari banyak pattern modern: counter privat, factory function, module pattern.

💡 Closure di mana-mana. Setiap kali kamu pakai callback yang akses variabel dari luar fungsi callback-nya, kamu lagi pakai closure. React hooks (useState, useEffect) dasarnya closure. Event handler dengan akses state? Closure. Paham closure = paham 60% pattern JavaScript modern.

function buatSapa(salam) {
  return function(nama) {
    return salam + ", " + nama + "!";
  };
}

const sapaIndo = buatSapa("Halo");
sapaIndo("Budi");  // "Halo, Budi!"
sapaIndo("Ani");   // "Halo, Ani!"

sapaIndo tetap mengingat nilai salam meskipun buatSapa sudah selesai.

<title id="closure-t">Lexical scope: inner function tetap akses variabel outer setelah outer return.</title>Closure: inner function "menggenggam" outer scope// Outer scope (function buatSapa)salam = "Halo"return function(nama) { return salam + nama;↑ akses outer var}Outer return → variabel salam tetap hidup karena inner butuh.
Garbage collector tidak buang salam selama inner function masih ada referensi.

Kegunaan closure:

  1. Data privacy — menyembunyikan variabel dari luar
  2. Factory functions — membuat fungsi yang dikustomisasi
  3. Counter/state — menyimpan state tanpa variabel global
function counter() {
  let count = 0;
  return {
    tambah: () => ++count,
    nilai: () => count
  };
}

const c = counter();
c.tambah(); // 1
c.tambah(); // 2
c.nilai();  // 2
// count tidak bisa diakses langsung dari luar!

🎭 Analogi sehari-hari

Pernah pinjem buku dari perpus terus pas keluar bawa juga catatan kecil yang kamu tulis selama baca? Walaupun perpusnya udah tutup (function luar selesai), kamu tetap bisa baca catatannya — karena udah kamu kantongin. Itu closure: function dalem "kantongin" variabel dari scope luar, dan tetap bisa pakai walaupun scope itu udah lama bubar.

Counter pattern itu kayak celengan ayam jago — kamu cuma bisa masukin koin (tambah()) atau ngintip nominalnya lewat method (nilai()). Dari luar gak ada yang bisa langsung buka isi celengan, dilindungi cangkangnya. Encapsulation tanpa harus pake class — privasi data ala JavaScript jaman dulu yang masih relevan banget sampai sekarang.

⚠️ Jebakan yang sering ditemui:

  • Loop dengan var + closure — semua callback baca variabel loop yang sama (variable bocor). for (var i = 0; i < 3; i++) setTimeout(() => log(i)) print 3, 3, 3. Pakai let → print 0, 1, 2.
  • Memory leak via closure — closure menahan seluruh scope, bukan cuma var yang dipakai. DOM element + closure besar = leak. Set null saat tidak dipakai.
  • Stale closure — di React, callback yang di-define dalam useEffect "freeze" var saat itu. Pakai ref atau function setState (prev) => ....
  • Shared state bug — multiple closure share variabel yang sama, terus mutate. Bug subtle. Pakai const + struktur baru.
  • this di closure — closure mewarisi this dari scope luar (kalau arrow). Kalau function biasa, this baru per pemanggilan.

🧪 Tebakan cepat — closure bug klasik. Tanpa run kode, tebak output:

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}

Jawaban: 3, 3, 3. Bukan 0, 1, 2. Karena var shared scope di seluruh loop, semua callback baca i yang sama (nilai akhir = 3). Fix: ganti var ke let — tiap iterasi let bikin block scope baru, callback masing-masing nyimpen snapshot i waktu itu. Output jadi 0, 1, 2. Bug klasik yang ngajarin kamu kenapa var ditinggalin.

TL;DR: Closure = function yang "kantongin" variabel dari scope luar, tetep akses walau scope luar udah selesai. Fondasi banyak pattern modern: counter privat, factory function, React hooks (useState/useEffect dasarnya closure). Setiap callback yang akses variabel dari fungsi pembungkusnya = closure.

Yang akan kamu pelajari