หากลบองค์ประกอบ DOM แล้วผู้ฟังจะถูกลบออกจากหน่วยความจำด้วยหรือไม่
หากลบองค์ประกอบ DOM แล้วผู้ฟังจะถูกลบออกจากหน่วยความจำด้วยหรือไม่
คำตอบ:
JavaScript ธรรมดา
หากองค์ประกอบ DOM ที่ถูกลบนั้นไม่มีการอ้างอิง (ไม่มีการอ้างอิงที่ชี้ไปที่มัน) ใช่ - องค์ประกอบนั้นจะถูกเก็บรวบรวมโดยตัวรวบรวมขยะเช่นเดียวกับตัวจัดการเหตุการณ์ / ผู้ฟังที่เกี่ยวข้อง
var a = document.createElement('div');
var b = document.createElement('p');
// Add event listeners to b etc...
a.appendChild(b);
a.removeChild(b);
b = null;
// A reference to 'b' no longer exists
// Therefore the element and any event listeners attached to it are removed.
อย่างไรก็ตาม; หากมีการอ้างอิงที่ยังคงชี้ไปที่องค์ประกอบดังกล่าวองค์ประกอบและผู้ฟังเหตุการณ์จะถูกเก็บไว้ในหน่วยความจำ
var a = document.createElement('div');
var b = document.createElement('p');
// Add event listeners to b etc...
a.appendChild(b);
a.removeChild(b);
// A reference to 'b' still exists
// Therefore the element and any associated event listeners are still retained.
jQuery
มันจะยุติธรรมที่จะคิดว่าวิธีการที่เกี่ยวข้องใน jQuery (เช่นremove()
) จะทำงานในลักษณะเดียวกัน (การพิจารณาremove()
นั้นถูกเขียนโดยใช้removeChild()
ตัวอย่าง)
แต่นี้ไม่เป็นความจริง ; ไลบรารี jQuery จริง ๆ แล้วมีวิธีการภายใน (ซึ่งไม่มีเอกสารและในทางทฤษฎีสามารถเปลี่ยนแปลงได้ตลอดเวลา) เรียกว่าcleanData()
(นี่คือสิ่งที่วิธีนี้ดูเหมือน ) ซึ่งจะล้างข้อมูล / เหตุการณ์ทั้งหมดที่เกี่ยวข้องกับองค์ประกอบโดยอัตโนมัติเมื่อลบออกจาก DOM (ไม่ว่าจะผ่านทางนี้. remove()
, empty()
, html("")
ฯลฯ )
เบราว์เซอร์รุ่นเก่า - IE รุ่นเก่าโดยเฉพาะ - เป็นที่รู้กันว่ามีปัญหาการรั่วไหลของหน่วยความจำเนื่องจากผู้ฟังเหตุการณ์เก็บการอ้างอิงถึงองค์ประกอบที่แนบมาด้วย
หากคุณต้องการคำอธิบายเชิงลึกเพิ่มเติมเกี่ยวกับสาเหตุรูปแบบและโซลูชันที่ใช้เพื่อแก้ไขการรั่วไหลของหน่วยความจำรุ่น IE ดั้งเดิมฉันขอแนะนำให้คุณอ่านบทความ MSDN นี้เกี่ยวกับการทำความเข้าใจและแก้ไขรูปแบบการรั่วไหลของ Internet Explorer
อีกบทความที่เกี่ยวข้องกับเรื่องนี้:
การลบผู้ฟังด้วยตัวเองอาจเป็นนิสัยที่ดีที่จะเข้าไปในกรณีนี้ (เฉพาะในกรณีที่หน่วยความจำมีความสำคัญต่อแอปพลิเคชันของคุณ
remove
วิธีการ ส่วนใหญ่ DOM จะเพิ่งถูกลบทิ้งอย่างสมบูรณ์ (เช่นลิงค์เทอร์โบหรือบางอย่าง) ฉันสงสัยว่าหน่วยความจำจะได้รับผลกระทบอย่างไรถ้าฉันdocument.body.innerHTML = ''
...
เกี่ยวกับ jQuery:
. Remove () วิธีการใช้องค์ประกอบออกจาก DOM ใช้. Remove () เมื่อคุณต้องการลบองค์ประกอบเองรวมถึงทุกสิ่งที่อยู่ภายใน นอกเหนือจากองค์ประกอบเองเหตุการณ์ที่ถูกผูกไว้ทั้งหมดและข้อมูล jQuery ที่เกี่ยวข้องกับองค์ประกอบจะถูกลบออก หากต้องการลบองค์ประกอบโดยไม่ลบข้อมูลและเหตุการณ์ให้ใช้. debet () แทน
การอ้างอิง: http://api.jquery.com/remove/
jQuery v1.8.2 .remove()
รหัสที่มา:
remove: function( selector, keepData ) {
var elem,
i = 0;
for ( ; (elem = this[i]) != null; i++ ) {
if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
if ( !keepData && elem.nodeType === 1 ) {
jQuery.cleanData( elem.getElementsByTagName("*") );
jQuery.cleanData( [ elem ] );
}
if ( elem.parentNode ) {
elem.parentNode.removeChild( elem );
}
}
}
return this;
}
เห็นได้ชัดว่า jQuery ใช้ node.removeChild()
ตามนี้: https://developer.mozilla.org/en-US/docs/DOM/Node.removeChild ,
The removed child node still exists in memory, but is no longer part of the DOM. You may reuse the removed node later in your code, via the oldChild object reference.
เช่นผู้ฟังเหตุการณ์อาจถูกลบ แต่node
ยังคงอยู่ในหน่วยความจำ
removeChild
ไม่ง่าย ทั้งสองยังส่งคืนการอ้างอิงที่คุณอาจเก็บไว้ติดตั้งใหม่ (ซึ่งในกรณีนี้มันจะยังคงอยู่ในหน่วยความจำ) หรือวิธีการขว้างปา
อย่าลังเลที่จะดูฮีปเพื่อดูการรั่วไหลของหน่วยความจำในตัวจัดการเหตุการณ์ที่อ้างอิงถึงองค์ประกอบด้วยการปิดและองค์ประกอบที่อ้างอิงถึงตัวจัดการเหตุการณ์
ตัวรวบรวมขยะไม่ชอบการอ้างอิงแบบวงกลม
กรณีการรั่วไหลของหน่วยความจำปกติ: ยอมรับว่าวัตถุมีการอ้างอิงถึงองค์ประกอบ องค์ประกอบนั้นมีการอ้างอิงถึงตัวจัดการ และตัวจัดการมีการอ้างอิงไปยังวัตถุ วัตถุนั้นอ้างอิงวัตถุอื่นจำนวนมาก วัตถุนี้เป็นส่วนหนึ่งของคอลเลกชันที่คุณคิดว่าคุณทิ้งไปโดยไม่อ้างถึงจากคอลเลกชันของคุณ => วัตถุทั้งหมดและทั้งหมดที่อ้างถึงจะยังคงอยู่ในหน่วยความจำจนกระทั่งออกจากหน้า => คุณต้องคิดถึงวิธีการฆ่าแบบสมบูรณ์สำหรับคลาสอ็อบเจ็กต์ของคุณหรือเชื่อถือเฟรมเวิร์ก mvc
ยิ่งกว่านั้นอย่าลังเลที่จะใช้ส่วนรักษาต้นไม้ของเครื่องมือพัฒนา Chrome
เพียงขยายคำตอบอื่น ๆ ...
ตัวจัดการเหตุการณ์ที่ได้รับมอบหมายจะไม่ถูกลบออกเมื่อมีการลบองค์ประกอบ
$('body').on('click', '#someEl', function (event){
console.log(event);
});
$('#someEL').remove(); // removing the element from DOM
ตรวจสอบตอนนี้:
$._data(document.body, 'events');
เกี่ยวกับjQuery
วิธีการทั่วไปต่อไปนี้จะลบการสร้างอื่น ๆ เช่นตัวจัดการข้อมูลและเหตุการณ์:
นอกเหนือจากองค์ประกอบเองเหตุการณ์ที่ถูกผูกไว้ทั้งหมดและข้อมูล jQuery ที่เกี่ยวข้องกับองค์ประกอบจะถูกลบออก
เพื่อหลีกเลี่ยงการรั่วไหลของหน่วยความจำ jQuery จะลบการสร้างอื่น ๆ เช่นข้อมูลและตัวจัดการเหตุการณ์จากองค์ประกอบลูกก่อนที่จะลบองค์ประกอบเอง
นอกจากนี้ jQuery จะลบการสร้างอื่น ๆ เช่นข้อมูลและตัวจัดการเหตุการณ์จากองค์ประกอบลูกก่อนที่จะแทนที่องค์ประกอบเหล่านั้นด้วยเนื้อหาใหม่
ใช่ตัวเก็บขยะจะลบออกเช่นกัน อาจไม่เป็นเช่นนั้นกับเบราว์เซอร์รุ่นเก่าเสมอไป