Pengenalan
Bahasa peringkat rendah, seperti C, mempunyai primitif pengurusan memori peringkat rendah, seperti malloc() dan free(). Primitif memori JavaScript, sebaliknya, diperuntukkan apabila pembolehubah (objek, rentetan, dll.) dicipta dan kemudian "secara automatik" dibebaskan apabila ia tidak lagi digunakan. Yang terakhir dipanggil kutipan sampah. "Automatik" ini mengelirukan dan memberikan JavaScript (dan bahasa peringkat tinggi lain) ilusi bahawa mereka tidak perlu memikirkan pengurusan memori.
Kitaran hayat ingatan
Tidak kira apa bahasa pengaturcaraan, kitaran hayat memori pada asasnya adalah sama:
1. Peruntukkan memori yang anda perlukan
2. Gunakannya (baca, tulis)
3. Lepaskan apabila tidak digunakan ps: Ia mempunyai maksud yang sama dengan "memasukkan gajah dalam peti sejuk"
Bahagian pertama dan kedua proses adalah jelas dalam semua bahasa. Langkah terakhir adalah jelas dalam bahasa peringkat rendah, tetapi dalam bahasa peringkat tinggi seperti JavaScript, langkah terakhir tidak jelas.
Peruntukan memori JavaScript
Permulaan pembolehubah
Untuk tidak membuat pengaturcara bimbang tentang peruntukan, JavaScript melengkapkan peruntukan memori semasa mentakrifkan pembolehubah.
var o = {
a: 1,
b: batal
}; // Peruntukkan memori untuk objek dan pembolehubah yang mengandunginya
var a = [1, null, "abra"]; // Peruntukkan memori untuk tatasusunan dan pembolehubah yang mengandunginya (sama seperti objek)
fungsi f(a){
kembalikan 2;
} // Peruntukkan memori untuk fungsi (objek boleh panggil)
// Ungkapan fungsi juga boleh memperuntukkan objek
someElement.addEventListener('klik', function(){
someElement.style.backgroundColor = 'biru';
}, palsu);
Peruntukan memori melalui panggilan fungsi
Sesetengah panggilan fungsi menghasilkan peruntukan memori objek:
Sesetengah kaedah memperuntukkan pembolehubah baharu atau objek baharu:
var a = ["ouais ouais", "nan nan"];
var a2 = ["generasi", "nan nan"];
var a3 = a.concat(a2); // Terdapat empat elemen dalam tatasusunan baharu yang menghubungkan tatasusunan a dan tatasusunan a2.
Penggunaan nilai
Proses menggunakan nilai sebenarnya adalah operasi membaca dan menulis memori yang diperuntukkan, yang bermaksud anda boleh menulis pembolehubah atau nilai atribut objek, dan juga lulus parameter fungsi.
Lepaskan memori apabila ia tidak diperlukan lagi
Kebanyakan masalah pengurusan ingatan berlaku pada peringkat ini. Tugas yang paling sukar di sini adalah untuk mencari bahawa memori yang diperuntukkan sememangnya tidak diperlukan lagi. Ia selalunya memerlukan pembangun untuk menentukan bahagian memori dalam program yang tidak lagi diperlukan dan membebaskannya.
Penterjemah bahasa peringkat tinggi membenamkan "pengumpul sampah" yang tugas utamanya adalah untuk menjejaki peruntukan dan penggunaan memori supaya ia boleh dikeluarkan secara automatik apabila memori yang diperuntukkan tidak lagi digunakan. Proses ini adalah anggaran, kerana mengetahui sama ada sekeping ingatan tertentu diperlukan tidak dapat ditentukan (tidak boleh diselesaikan oleh algoritma tertentu).
Pengumpulan Sampah
Seperti yang dinyatakan di atas, masalah mencari secara automatik sama ada sesetengah memori "tidak diperlukan lagi" tidak dapat ditentukan. Oleh itu, pelaksanaan kutipan sampah hanya dapat menyelesaikan masalah umum pada tahap yang terhad. Bahagian ini menerangkan konsep yang diperlukan untuk memahami algoritma kutipan sampah utama dan hadnya.
Petikan
Algoritma kutipan sampah terutamanya bergantung pada konsep rujukan. Dalam konteks pengurusan ingatan, jika objek mempunyai kebenaran untuk mengakses objek lain (secara tersirat atau eksplisit), ia dipanggil objek yang merujuk objek lain. Sebagai contoh, objek Javascript mempunyai rujukan kepada prototaipnya (rujukan tersirat) dan rujukan kepada sifatnya (rujukan eksplisit).Di sini, konsep "objek" bukan sahaja objek Javascript khas, tetapi juga termasuk skop fungsi (atau skop leksikal global).
Rujukan mengira kutipan sampah
Ini adalah algoritma kutipan sampah yang paling mudah. Algoritma ini memudahkan takrifan "sama ada objek tidak lagi diperlukan" sebagai "sama ada objek itu mempunyai objek lain yang merujuknya." Jika tiada rujukan yang menunjuk kepada objek (rujukan sifar), objek akan dituntut semula oleh mekanisme kutipan sampah.Contohnya
o = 1; // Sekarang, rujukan asal "objek ini" digantikan dengan o2
// Sekarang, "objek ini" mempunyai dua rujukan, satu ialah o2 dan satu lagi ialah oa
// Dia boleh menjadi sampah yang dikutip
// Walau bagaimanapun, objek atributnya a masih dirujuk oleh oa, jadi ia tidak boleh dikitar semula lagi
// Ia boleh menjadi sampah yang dikutip
Batasan: rujukan bulat
Penghadan algoritma mudah ini ialah jika satu objek merujuk yang lain (membentuk rujukan bulat), ia mungkin "tidak diperlukan lagi", tetapi ia tidak akan dikitar semula.
}
// Dua objek dicipta dan merujuk antara satu sama lain, membentuk gelung
// Mereka tidak akan meninggalkan skop fungsi selepas dipanggil
// Jadi ia tidak lagi berguna dan boleh dikitar semula
// Walau bagaimanapun, algoritma pengiraan rujukan mengambil kira bahawa kesemuanya mempunyai sekurang-kurangnya satu rujukan antara satu sama lain, jadi ia tidak akan dikitar semula
Contoh praktikal
IE 6, 7 melakukan pengiraan rujukan kitar semula pada objek DOM. Masalah biasa bagi mereka ialah kebocoran ingatan:
Algoritma tanda dan jelas
Algoritma ini memudahkan takrifan "sama ada objek tidak lagi diperlukan" sebagai "sama ada objek itu boleh diperolehi."
Algoritma ini menganggap menyediakan objek yang dipanggil root (dalam Javascript, root ialah objek global). Secara berkala, pengumpul sampah akan bermula pada akar, mencari semua objek yang dirujuk dari akar, dan kemudian mencari objek yang dirujuk oleh objek ini... Bermula dari akar, pengumpul sampah akan mencari semua objek yang boleh diperolehi dan semua objek yang tidak dapat diperolehi.
Algoritma ini lebih baik daripada yang sebelumnya, kerana "objek dengan rujukan sifar" sentiasa tidak dapat diperoleh, tetapi sebaliknya tidak semestinya benar, rujuk kepada "rujukan kitaran".
Sehingga 2012, semua penyemak imbas moden menggunakan algoritma kutipan sampah tanda-dan-sapu. Semua penambahbaikan pada algoritma kutipan sampah JavaScript adalah berdasarkan penambahbaikan pada algoritma mark-sweep dan tidak menambah baik algoritma mark-sweep itu sendiri dan takrifan ringkasnya tentang "sama ada objek tidak diperlukan lagi."
Rujukan pekeliling tidak lagi menjadi masalah
Dalam contoh di atas, selepas panggilan fungsi kembali, kedua-dua objek tidak boleh diperolehi daripada objek global. Oleh itu, mereka akan dikutip oleh pemungut sampah.
Dalam contoh kedua, sebaik sahaja div dan pengendali acaranya tidak dapat dicapai dari akar, mereka akan dikumpulkan oleh pemungut sampah.
Keterbatasan: Objek mestilah tidak boleh dicapai dengan jelas
Walaupun ini adalah had, ia jarang dilampaui, itulah sebabnya sebenarnya tidak ramai yang mengambil berat tentang mekanisme kutipan sampah.