Lompat ke konten
Kembali ke modul

Cara JavaScript Berjalan: Engine, Event Loop, Async · 2/9

Memori: stack, heap, dan garbage collection

Di mana nilai-nilaimu sebenarnya tinggal, dan kenapa kamu hampir tidak pernah membebaskannya sendiri.

Baca 22 menit

Setelah pelajaran ini kamu bisa

  • Menyebutkan apa yang tinggal di stack dan apa yang tinggal di heap
  • Menjelaskan apa yang membuat sebuah value layak dibersihkan
  • Menyebutkan empat cara kode JavaScript membocorkan memori
  • Membersihkan timer dan listener dengan benar

Kamu tidak pernah memanggil free() di JavaScript. Memori dikembalikan untukmu — tapi hanya untuk value yang sudah tidak bisa dijangkau apa pun lagi. Memahami "dijangkau" adalah pembeda antara kode yang jalan berminggu-minggu dan kode yang harus di-restart tiap malam.

Stack dan heap

StackHeap
MenyimpanPrimitive, dan reference ke objectObject-nya sendiri
UkuranKecil dan tetapBesar dan bisa bertambah
Dikelola olehOtomatis, saat function masuk dan keluarGarbage collector
KecepatanSangat cepatLebih lambat
Bisa habis?Ya — stack overflowYa — out of memory

Inilah alasan mekanis di balik pelajaran soal reference di modul sebelumnya. const user = { name: "Ana" } menaruh object-nya di heap dan alamatnya di stack. Menyalin variable-nya berarti menyalin alamatnya, bukan object-nya.

Keterjangkauan

Collector-nya mulai dari sekumpulan root — object global, call stack saat ini, closure yang aktif — lalu mengikuti setiap reference yang bisa dijangkaunya. Apa pun yang tidak pernah ia sampai ke sana berarti tak terjangkau, dan memorinya bisa dikembalikan. Tidak ada faktor lain: bukan soal kamu mengisinya null atau tidak, bukan soal function yang membuatnya sudah return atau belum.

Coba sendiri

Hasil

Tekan Jalankan untuk melihat hasilnya.

Ini jalan di browser kamu, di dalam sandbox. Apa pun yang kamu tulis di sini tidak bisa merusak situs.

Empat cara kode nyata membocorkan memori

Kebocoran adalah memori yang tetap terjangkau padahal kamu sudah selesai dengannya. Di JavaScript penyebabnya hampir selalu salah satu dari empat ini.

js
// 1. A timer nobody stopped. It holds its callback, and the callback's closure.
const id = setInterval(() => sync(bigObject), 1000);
// fix:
clearInterval(id);

// 2. A listener nobody removed. The handler keeps the whole component alive.
element.addEventListener("scroll", onScroll);
// fix:
element.removeEventListener("scroll", onScroll);   // the SAME function reference

// 3. A cache that only ever grows.
const cache = new Map();
function remember(key, value) { cache.set(key, value); }   // never deleted
// fix: bound the size, or use a WeakMap when the key is an object

// 4. A detached DOM node still referenced from JavaScript.
const removed = document.getElementById("row");
removed.remove();          // gone from the page
// but `removed` still points at it, so it cannot be collected
Coba sendiri

Hasil

Tekan Jalankan untuk melihat hasilnya.

Ini jalan di browser kamu, di dalam sandbox. Apa pun yang kamu tulis di sini tidak bisa merusak situs.

Tugas praktik

Di Chrome DevTools, buka tab Memory dan ambil heap snapshot dari aplikasi mana pun. Lalu pakai aplikasinya secara intensif, ambil snapshot kedua, dan pakai tampilan "Comparison" untuk melihat apa yang bertambah. Kalau object sebuah component terus bertambah setelah kamu berpindah halaman darinya, kamu menemukan kebocoran nyata.

Hasil yang diharapkan

Daftar perbandingan yang menunjukkan constructor mana yang bertambah object-nya.