Rumah  >  Artikel  >  hujung hadapan web  >  Pengenalan kepada pengurusan memori JavaScript_kemahiran javascript

Pengenalan kepada pengurusan memori JavaScript_kemahiran javascript

WBOY
WBOYasal
2016-05-16 16:09:40906semak imbas

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.

Salin kod Kod adalah seperti berikut:

var n = 123; // Peruntukkan memori kepada pembolehubah berangka
var s = "azerty"; // Berikan jenis aksara

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:

Salin kod Kod adalah seperti berikut:

var d = new Date();
var e = document.createElement('div'); //Tetapkan elemen DOM

Sesetengah kaedah memperuntukkan pembolehubah baharu atau objek baharu:

Salin kod Kod adalah seperti berikut:

var s = "azerty";
var s2 = s.substr(0, 3); // s2 ialah rentetan baharu
//Oleh kerana rentetan adalah invarian, JavaScript mungkin tidak memperuntukkan memori, tetapi hanya menyimpan julat 0-3.

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


Salin kod Kod adalah seperti berikut:
var o = {
a: {
b:2
}
};
// Dua objek dicipta, satu dirujuk sebagai harta benda yang lain, dan satu lagi ditugaskan kepada pembolehubah o
// Jelas sekali, tiada satu pun daripada mereka boleh menjadi sampah yang dikutip
var o2 = o; // Pembolehubah o2 ialah rujukan kedua kepada "objek ini"

o = 1; // Sekarang, rujukan asal "objek ini" digantikan dengan o2

var oa = o2.a; // Rujuk sifat "objek ini"

// Sekarang, "objek ini" mempunyai dua rujukan, satu ialah o2 dan satu lagi ialah oa

o2 = "yo"; // Objek asal kini mempunyai rujukan sifar

// Dia boleh menjadi sampah yang dikutip
// Walau bagaimanapun, objek atributnya a masih dirujuk oleh oa, jadi ia tidak boleh dikitar semula lagi

oa = null; // Objek dengan atribut kini juga mempunyai rujukan sifar

// 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.


Salin kod Kod adalah seperti berikut:
fungsi f(){
var o = {};
var o2 = {};
o.a = o2; // o rujukan o2
o2.a = o; // o2 merujuk kepada o
kembalikan "azerty";

}

f();

// 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:


Salin kod Kod adalah seperti berikut:
var div = document.createElement("div");
div.onclick = function(){
doSomething();
};
// Div mempunyai rujukan kepada atribut pengendalian acara onclick
// Pengendali acara juga mempunyai rujukan kepada div yang boleh diakses dalam skop fungsi
// Rujukan pekeliling ini akan menyebabkan kedua-dua objek tidak menjadi sampah yang dikutip

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.

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn