यदि एक DOM एलिमेंट हटा दिया जाता है, तो क्या उसके श्रोताओं को मेमोरी से भी हटा दिया जाता है?


336

यदि एक DOM एलिमेंट हटा दिया जाता है, तो क्या उसके श्रोताओं को मेमोरी से भी हटा दिया जाता है?

जवाबों:


307

आधुनिक ब्राउज़र

सादा जावास्क्रिप्ट

यदि कोई 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 लेख को पढ़ने की सलाह देता हूं

इससे जुड़े कुछ और लेख:

स्वयं श्रोताओं को हटा देना संभवतः इस मामले में आने के लिए एक अच्छी आदत होगी (केवल अगर स्मृति आपके आवेदन के लिए महत्वपूर्ण है और आप वास्तव में ऐसे ब्राउज़रों को लक्षित कर रहे हैं)।


22
एक तत्व पर हटाने () विधि का उपयोग करते समय jquery प्रलेखन के अनुसार, सभी घटना श्रोताओं को स्मृति से हटा दिया जाता है। यह उस तत्व को प्रभावित करता है जो स्वयं को और सभी बच्चे को नोड करता है। यदि आप ईवेंट श्रोताओं को स्मृति में रखना चाहते हैं, तो आपको इसके बजाय .detach () का उपयोग करना चाहिए। उपयोगी जब हटाए गए तत्वों को डोम पर फिर से डाला जा रहा है।
लोथ्रे

1
यदि तत्व में बाल हाथी शामिल हैं, तो क्या यह बच्चे के तत्वों पर भी घटना सुनने वालों को अलग कर देगा?
CBeTJlu4ok

1
@ लोथ्रे 1 - यह removeविधि का उपयोग करते समय ही होता है । ज्यादातर समय डोम पूरी तरह से मिट जाएगा। (जैसे टर्बो लिंक या कुछ और)। मुझे आश्चर्य है कि अगर मैं करता हूं तो मेमोरी कैसे प्रभावित होती है document.body.innerHTML = ''...
vsync

1
मुझे "व्यक्तिगत अनुभव" से अधिक की आवश्यकता होगी, जैसे हार्ड डेटा और परीक्षण और स्पेक्स के लिंक अधिक हैं जो कहते हैं कि स्मृति नोड्स पर लगातार बनी रहती है जो अब दस्तावेज़ में नहीं हैं, यह सिर्फ सबूत के बिना किसी के शब्द पर भरोसा करना बहुत महत्वपूर्ण है :)
vsync

1
@ Lothre1 धन्यवाद - मैंने थोड़ा गहरा खोदा है और पाया है कि कैसे jQuery इस संबंध में नियमित जावास्क्रिप्ट से अलग कार्य करता है। उत्तर को अद्यतन किया है।
dsgriffin

23

jQuery के बारे में:

.remove () पद्धति डोम से तत्वों को निकालती है। .Remove () का उपयोग करें जब आप तत्व को स्वयं निकालना चाहते हैं, साथ ही इसके अंदर सब कुछ भी। तत्वों के अलावा, सभी बाध्य घटनाओं और तत्वों से जुड़े jQuery डेटा हटा दिए जाते हैं। डेटा और ईवेंट को हटाए बिना तत्वों को निकालने के लिए इसके बजाय .detach () का उपयोग करें।

संदर्भ: 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अभी भी स्मृति में मौजूद है।


3
आप केवल भ्रम जोड़ रहे हैं - jQuery ऐसा कुछ भी नहीं करता है जो हैंडलर के साथ है जो सरल removeChildनहीं होगा। दोनों आपको एक संदर्भ भी देते हैं जिसे आप बाद में रीटच करने के लिए रख सकते हैं (जिस स्थिति में यह स्पष्ट रूप से स्मृति में रहता है) या फेंकने का तरीका (जिस स्थिति में इसे अंततः जीसी द्वारा उठाया जाता है और हटा दिया जाता है)।
ओलेग वी। वोल्कोव

मै जानता हू। तो जहाँ आप एक सवाल संपादित किया है? क्योंकि मैं कसम खा सकता था कि पहले सवाल में डोम तत्व को हटाने के लिए jquery का उपयोग करने के बारे में कुछ था। अब मेरा जवाब मुझे लगता है जैसे मैं अपने अहंकार को खत्म करने के लिए चीजों को समझा रहा हूं। अरे, आप हमेशा नीचा दिखा सकते हैं
श्रीनाथ एस

8

इवेंट हैंडलर में मेमोरी लीक्स को देखने के लिए ढेर को देखने में संकोच न करें और एक क्लोजर के साथ एलिमेंट का रेफरेंस रखते हैं और ईवेंट हैंडलर का रेफरेंस रखते हुए एलिमेंट।

कचरा कलेक्टर को परिपत्र संदर्भ पसंद नहीं है।

सामान्य स्मृति रिसाव मामला: एक वस्तु को स्वीकार एक तत्व के लिए एक रेफरी है। उस तत्व में हैंडलर के लिए एक रेफरी है। और हैंडलर वस्तु के लिए एक रेफरी है। ऑब्जेक्ट में कई अन्य वस्तुओं के लिए refs है। यह ऑब्जेक्ट एक संग्रह का हिस्सा था जिसे आपको लगता है कि आपने इसे अपने संग्रह से अप्रकाशित करके फेंक दिया है। => संपूर्ण वस्तु और यह सब संदर्भित पृष्ठ से बाहर निकलने तक स्मृति में रहेगा। => आपको अपने ऑब्जेक्ट क्लास के लिए एक संपूर्ण हत्या विधि के बारे में सोचना होगा या उदाहरण के लिए एक mvc ढांचे पर भरोसा करना होगा।

इसके अलावा, क्रोम देव टूल्स के रिटेनिंग ट्री भाग का उपयोग करने में संकोच न करें।


8

बस अन्य उत्तर बढ़ा रहे हैं ...

तत्व हटाने पर प्रत्यायोजित ईवेंट हैंडलर नहीं निकाले जाएंगे।

$('body').on('click', '#someEl', function (event){
  console.log(event);
});

$('#someEL').remove(); // removing the element from DOM

अब जांचें:

$._data(document.body, 'events');

9
इवेंट हैंडलर शरीर से जुड़ा हुआ है और #someEl से नहीं, स्वाभाविक रूप से हैंडलर को तब तक नहीं हटाया जाना चाहिए जब तक कि शरीर अभी भी यहां नहीं है।
यांगशुन ताई

इसे मैन्युअल रूप से हटाया जा सकता है: stackoverflow.com/questions/22400907/…
4:43 बजे fangxing

7

के बारे में jQuery, निम्नलिखित आम तरीकों में भी इस तरह के डेटा और ईवेंट हैंडलर्स के रूप में अन्य निर्माणों को हटा देगा:

हटाना()

तत्वों के अलावा, सभी बाध्य घटनाओं और तत्वों से जुड़े jQuery डेटा हटा दिए जाते हैं।

खाली ()

मेमोरी लीक से बचने के लिए, jQuery स्वयं तत्वों को हटाने से पहले अन्य तत्वों जैसे कि बाल तत्वों से डेटा और घटना संचालकों को हटा देता है।

एचटीएमएल ()

इसके अतिरिक्त, jQuery उन तत्वों को हटा देता है जैसे नए तत्व के साथ उन तत्वों को बदलने से पहले बाल तत्वों से डेटा और ईवेंट हैंडलर्स।


2

हां, कचरा इकट्ठा करने वाले उन्हें भी हटा देंगे। हालांकि हमेशा विरासत ब्राउज़रों के मामले में ऐसा नहीं हो सकता है।


7
आप बयान API दस्तावेज़, उदाहरण, आदि द्वारा समर्थित होना चाहिए
पाओलो Fulgoni
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.