Memahami kebocoran memori yang disebabkan oleh penutupan dan kesannya memerlukan contoh kod khusus
Dalam JavaScript, penutupan ialah konsep pengaturcaraan yang sangat biasa. Ia membolehkan kami mengakses pembolehubah dalam skop luar dari dalam fungsi, tetapi ia juga boleh menyebabkan kebocoran memori. Artikel ini akan memperkenalkan konsep dan prinsip penutupan dan masalah kebocoran memori yang mungkin disebabkannya, dan membantu pembaca memahami dengan lebih baik melalui contoh kod tertentu.
Penutupan sebenarnya adalah keupayaan sesuatu fungsi untuk mengakses dan mengingati skop leksikalnya apabila ia dicipta. Apabila fungsi mentakrifkan fungsi lain di dalam dan mengembalikan fungsi dalam sebagai nilai pulangan, fungsi dalam akan memegang rujukan kepada skop leksikal fungsi luarnya, membentuk penutupan.
Prinsip penutupan ialah mekanisme pengumpulan sampah JavaScript adalah berdasarkan pengiraan rujukan Apabila objek tidak lagi dirujuk oleh mana-mana objek lain, pemungut sampah akan mengosongkan ruang memori yang diduduki oleh objek itu secara automatik. Tetapi apabila penutupan wujud, kerana penutupan secara dalaman merujuk kepada pembolehubah fungsi luaran, skop fungsi luaran masih dirujuk, menyebabkan pengumpul sampah tidak dapat menuntut semula bahagian ruang memori ini, menyebabkan kebocoran memori.
Apabila menggunakan penutupan dalam fungsi mendengar acara, jika penutupan dalam fungsi mendengar acara merujuk kepada elemen DOM atau pembolehubah global yang lain, dan elemen atau pembolehubah ini tidak dikosongkan kemudiannya, penutupan akan sentiasa mengekalkan akses kepada objek ini juga menyebabkan kebocoran ingatan.
function createClosure() { var element = document.getElementById('myElement'); var closure = function() { console.log(element.textContent); }; element.addEventListener('click', closure); return closure; } var myClosure = createClosure();
createClosure
mencipta kod penutupan< >closure, yang merujuk kepada elemen DOM myElement
dan mengikat closure
sebagai fungsi panggil balik acara klik. Memandangkan penutupan closure
memegang rujukan kepada elemen DOM myElement
, apabila acara klik selesai, penutupan masih mengekalkan rujukan kepada elemen DOM, mengakibatkan kegagalan untuk menjadi sampah yang dikutip. Dalam kes ini, jika fungsi createClosure
dilaksanakan berulang kali, penutupan baharu akan dibuat setiap kali, tetapi penutupan lama tidak boleh dikeluarkan, menyebabkan kebocoran memori. Untuk menyelesaikan masalah ini, kami boleh melepaskan pendengar acara secara manual atau membatalkan rujukan penutupan pada masa yang sesuai, supaya pemungut sampah dapat melepaskan ruang memori yang diduduki. Ubah suai kod di atas seperti berikut: function createClosure() { var element = document.getElementById('myElement'); var closure = function() { console.log(element.textContent); }; function removeListener() { element.removeEventListener('click', closure); } element.addEventListener('click', closure); return removeListener; } var removeListener = createClosure(); //在不需要闭包的时候手动调用removeListener函数解除事件监听和闭包引用 removeListener();
removeListener
, panggil fungsi ini secara manual untuk mengalih keluar rujukan acara mendengar dan penutupan apabila penutupan tidak diperlukan, sekali gus mengelakkan masalah kebocoran memori. createClosure
函数创建了一个闭包closure
,该闭包引用了DOM元素myElement
,并将closure
作为点击事件的回调函数进行绑定。由于闭包closure
持有了DOM元素myElement
的引用,当点击事件完成后,闭包依然保留对DOM元素的引用,导致无法被垃圾回收。这种情况下,如果重复执行createClosure
函数,每次执行都会创建一个新的闭包,但旧的闭包却无法被释放,从而造成内存泄漏。
为了解决这个问题,我们可以在适当的时候手动解除事件监听或者取消闭包的引用,使垃圾回收器能够释放占用的内存空间。修改上述代码如下:
rrreee通过添加removeListener
Ringkasan
Atas ialah kandungan terperinci Ketahui lebih lanjut tentang kebocoran memori yang disebabkan oleh penutupan dan kesannya. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!