Perkenalan
Bahasa tingkat rendah, seperti C, memiliki primitif manajemen memori tingkat rendah, seperti malloc () dan bebas (). Di sisi lain, memori JavaScript dialokasikan ketika variabel (objek, string, dll.) Dibuat dan kemudian "secara otomatis" dibebaskan ketika mereka tidak lagi digunakan. Yang terakhir disebut koleksi sampah. "Otomatis" ini memadamkan dan memberikan ilusi JavaScript (dan bahasa tingkat tinggi lainnya): mereka dapat mengabaikan manajemen memori.
Siklus hidup memori
Tidak peduli bahasa pemrograman apa, siklus hidup memori pada dasarnya sama:
1. Alokasikan memori yang Anda butuhkan
2. Gunakan (baca, tulis)
3. Lepaskan PS: dan "Letakkan Gajah di Lemari Kulkas" berarti hal yang sama
Bagian pertama dan kedua dari proses ini jelas dalam semua bahasa. Langkah terakhir jelas dalam bahasa tingkat rendah, tetapi dalam bahasa tingkat tinggi seperti JavaScript, langkah terakhir tidak jelas.
Alokasi memori untuk JavaScript
Inisialisasi variabel
Agar tidak mengganggu programmer dengan masalah alokasi, JavaScript menyelesaikan alokasi memori saat mendefinisikan variabel.
Salinan kode adalah sebagai berikut:
var n = 123; // mengalokasikan memori ke variabel numerik
var s = "azerty"; // Berikan tipe karakter
var o = {
A: 1,
B: NULL
}; // mengalokasikan memori untuk objek dan variabel yang terkandung
var a = [1, null, "bra"]; // Alokasikan memori untuk array dan variabel berisi (seperti objek)
fungsi f (a) {
mengembalikan A + 2;
} // Alokasikan memori untuk fungsi (objek yang dapat dipanggil)
// Ekspresi fungsi juga dapat menetapkan objek
someelement.addeventListener ('click', function () {
someelement.style.backgroundColor = 'blue';
}, PALSU);
Alokasi memori melalui panggilan fungsi
Beberapa panggilan fungsi menghasilkan memori objek:
Salinan kode adalah sebagai berikut:
var d = tanggal baru ();
var e = document.createElement ('div'); // Tetapkan elemen DOM
Beberapa metode menetapkan variabel baru atau objek baru:
Salinan kode adalah sebagai berikut:
var s = "azerty";
var s2 = s.substr (0, 3); // S2 adalah string baru
// Karena String adalah invarian, JavaScript mungkin tidak mengalokasikan memori, tetapi hanya menyimpan kisaran 0-3.
var a = ["uanais uanais", "nan nan"];
var a2 = ["generasi", "nan nan"];
var a3 = a.concat (a2); // Ada empat elemen dalam array baru yang bergabung dengan Array A dan Array A2.
Penggunaan nilai
Proses penggunaan nilai sebenarnya adalah operasi baca dan tulis dari memori yang mengalokasikan, yang berarti bahwa variabel atau nilai properti objek dapat ditulis, atau bahkan parameter fungsi dapat dilewati.
Dibebaskan saat ingatan tidak lagi dibutuhkan
Sebagian besar masalah manajemen memori ada pada tahap ini. Tugas tersulit di sini adalah menemukan "memori yang dialokasikan memang tidak lagi diperlukan." Seringkali membutuhkan pengembang untuk menentukan bagian memori mana dalam program yang tidak lagi diperlukan dan membebaskannya.
Interpreter bahasa tingkat tinggi tertanam dengan "pengumpul sampah" dan tugas utamanya adalah melacak alokasi dan penggunaan memori sehingga akan secara otomatis dirilis ketika memori yang dialokasikan tidak lagi digunakan. Proses ini merupakan perkiraan karena tidak mungkin untuk menentukan apakah sepotong memori tertentu perlu ditentukan (tidak dapat diselesaikan dengan beberapa algoritma).
Daur Ulang Sampah
Seperti disebutkan di atas, pertanyaan tentang secara otomatis mencari apakah beberapa memori "tidak lagi diperlukan" tidak mungkin ditentukan. Oleh karena itu, implementasi pengumpulan sampah hanya dapat memecahkan masalah umum dengan keterbatasan. Bagian ini akan menjelaskan konsep yang diperlukan untuk memahami algoritma pengumpulan sampah utama dan keterbatasannya.
Mengutip
Algoritma pengumpulan sampah terutama mengandalkan konsep referensi. Dalam lingkungan yang dikelola memori, jika suatu objek memiliki izin untuk mengakses objek lain (secara implisit atau eksplisit), itu disebut objek yang mengacu pada objek lain. Misalnya, objek JavaScript memiliki referensi ke prototipe (referensi implisit) dan referensi ke propertinya (referensi eksplisit).
Di sini, konsep "objek" tidak hanya objek JavaScript khusus, tetapi juga ruang lingkup fungsi (atau ruang lingkup leksikal global).
Koleksi Hitungan Hitungan Referensi
Ini adalah algoritma pengumpulan sampah termudah. Algoritma ini menyederhanakan "apakah objek tidak lagi diperlukan" sebagai "apakah objek memiliki objek lain yang dirujuk kepadanya". Jika tidak ada referensi yang menunjuk ke objek (referensi nol), objek akan didaur ulang oleh mekanisme pengumpulan sampah.
Misalnya
Salinan kode adalah sebagai berikut:
var o = {
A: {
B: 2
}
};
// Dua objek dibuat, satu direferensikan sebagai atribut yang lain, dan yang lainnya ditugaskan ke variabel o
// Jelas, tidak ada yang bisa dikumpulkan dengan sampah
var o2 = o; // Variabel O2 adalah referensi kedua untuk "objek ini"
o = 1; // Sekarang, referensi asli o "objek ini" digantikan oleh O2
var oa = o2.a; // Referensi properti A "objek ini"
// Sekarang, ada dua referensi untuk "objek ini", satu adalah O2 dan yang lainnya adalah OA
o2 = "yo"; // Objek asli sekarang nol referensi
// dia bisa didaur ulang
// Namun, objek propertinya A masih dirujuk oleh OA, jadi itu belum dapat didaur ulang
oa = null; // Objek dengan properti A sekarang juga dirujuk oleh nol
// itu bisa dikumpulkan sampah
Batasan: Referensi Daur Ulang
Algoritma sederhana ini memiliki batasan bahwa jika suatu objek mengacu pada yang lain (membentuk referensi melingkar), mereka mungkin "tidak lagi membutuhkannya", tetapi mereka tidak akan didaur ulang.
Salinan kode adalah sebagai berikut:
fungsi f () {
var o = {};
var o2 = {};
oa = o2; // O Referensi O2
o2.a = o; // o2 kutipan o
kembali "Azerty";
}
F();
// Dua objek dibuat dan direferensikan satu sama lain, membentuk loop
// Mereka tidak akan meninggalkan ruang lingkup fungsi setelah dipanggil
// Jadi mereka tidak berguna dan dapat didaur ulang
// Namun, algoritma penghitungan referensi memperhitungkan bahwa mereka memiliki referensi satu sama lain setidaknya sekali, jadi mereka tidak akan didaur ulang
Contoh praktis
IE 6, 7 Daur Ulang Penghitungan Referensi pada Objek DOM. Masalah umum bagi mereka adalah kebocoran memori:
Salinan kode adalah sebagai berikut:
var div = document.createElement ("div");
div.onClick = function () {
dosomething ();
};
// Div memiliki referensi yang menunjuk ke event property property eventsing onclick
// Penanganan acara juga memiliki referensi ke DIV yang dapat diakses dalam lingkup fungsi
// referensi melingkar ini akan menyebabkan kedua objek dikumpulkan
Algoritma Mark-Clearing
Algoritma ini menyederhanakan "apakah objek tidak lagi diperlukan" sebagai "apakah objek tersedia".
Algoritma ini mengasumsikan pengaturan objek yang disebut root (dalam javascript, root adalah objek global). Secara teratur, pengumpul sampah akan mulai dari root, menemukan semua objek yang dirujuk dari root, dan kemudian menemukan objek yang dirujuk oleh objek -objek ini ... Mulai dari root, pengumpul sampah akan menemukan semua objek yang dapat diperoleh dan semua objek yang tidak dapat diperoleh.
Algoritma ini lebih baik dari yang sebelumnya, karena "objek dengan nol referensi" selalu tidak tersedia, tetapi sebaliknya, itu tidak selalu benar, lihat "referensi melingkar".
Sejak 2012, semua browser modern telah menggunakan algoritma koleksi sampah tag-bersih. Semua perbaikan pada algoritma pengumpulan sampah JavaScript didasarkan pada peningkatan algoritma pembersihan tag, tanpa meningkatkan algoritma pembersihan tag itu sendiri dan definisi yang disederhanakan tentang apakah objek tidak lagi diperlukan.
Referensi melingkar tidak lagi menjadi masalah
Dalam contoh di atas, setelah panggilan fungsi kembali, kedua objek tidak dapat diambil dari objek global. Karena itu, mereka akan didaur ulang oleh pengumpul sampah.
Contoh kedua juga, setelah div dan pemrosesan acara tidak dapat diambil dari akar, mereka akan didaur ulang oleh pengumpul sampah.
Batasan: Objek tidak perlu secara eksplisit tidak tersedia
Meskipun ini adalah batasan, jarang menerobos, itulah sebabnya pada kenyataannya, beberapa orang peduli dengan mekanisme pengumpulan sampah.