2010-09-24 16 views
45

मेरा जावास्ट्रिप कोड LI तत्वों की एक सूची बनाता है। जब मैं सूची अद्यतन करता हूं, तो स्मृति उपयोग बढ़ता है और कभी नीचे नहीं जाता है। मैंने एसआईईवी में परीक्षण किया और यह दिखाता है कि ब्राउज़र उन सभी तत्वों को रखता है जिन्हें $.remove() या $.empty jQuery आदेशों द्वारा हटाया जाना था।मेमोरी लीक के बिना डीओएम तत्वों को कैसे हटाया जाए?

स्मृति रिसाव के बिना डोम नोड्स को निकालने के लिए मुझे क्या करना चाहिए?

विशिष्ट कोड के लिए my other question देखें।

उत्तर

8

क्या आपने कोई ईवेंट श्रोताओं को हटा दिया है? वह can cause memory leaks

+0

मैं भी प्रत्येक तत्व $ (this) .unbind() एचटीएमएल ("") के लिए कर हटाने(); – podeig

+2

मैंने सोचा कि jQuery तत्व ईवेंट हैंडलर को स्वचालित रूप से हटा देता है, जब आप element करते हैं .remove(), नहीं? – jayarjo

+0

@jayarjo - यह – vsync

43

डीओएम सभी डोम नोड्स को संरक्षित करता है, भले ही उन्हें डीओएम पेड़ से हटा दिया गया हो, फिर भी इन नोड्स को हटाने का एकमात्र तरीका पृष्ठ रीफ्रेश करना है (यदि आप सूची को आईफ्रेम में डालते हैं तो रीफ्रेश नहीं होगा के रूप में उल्लेखनीय हो)

अन्यथा, आप समस्या के लिए प्रतीक्षा करने के लिए पर्याप्त बुरा पाने के लिए है, जिन्हें ब्राउज़र कचरा कलेक्टर (कार्रवाई के लिए मजबूर है अप्रयुक्त नोड्स यहाँ) के मेगाबाइट के सैकड़ों

सर्वश्रेष्ठ अभ्यास नोड्स का पुन: उपयोग करने के लिए है में बात कर सकता है।

संपादित करें: यदि आप इसे इस तरह करना होगा

var garbageBin; 
window.onload = function() 
    { 
    if (typeof(garbageBin) === 'undefined') 
     { 
     //Here we are creating a 'garbage bin' object to temporarily 
     //store elements that are to be discarded 
     garbageBin = document.createElement('div'); 
     garbageBin.style.display = 'none'; //Make sure it is not displayed 
     document.body.appendChild(garbageBin); 
     } 
    function discardElement(element) 
     { 
     //The way this works is due to the phenomenon whereby child nodes 
     //of an object with it's innerHTML emptied are removed from memory 

     //Move the element to the garbage bin element 
     garbageBin.appendChild(element); 
     //Empty the garbage bin 
     garbageBin.innerHTML = ""; 
     } 
    } 

अपने संदर्भ में इसके इस्तेमाल के लिये: इस प्रयास करें

discardElement(this); 
+9

मुझे नहीं पता था कि "डोम सभी डोम नोड्स को सुरक्षित रखता है, भले ही उन्हें डीओएम पेड़ से हटा दिया गया हो" क्या आपका मतलब $ .remove() फ़ंक्शन करता है कुछ नहीं करो? – podeig

+0

कचरा कलेक्टर चलाने के लिए कितने मेगाबाइट का उपयोग किया जाना चाहिए। मुझे लगता है कि 150 एमबी पर्याप्त होना चाहिए। लेकिन यह मेरे लिए काम नहीं करता है। – podeig

+0

संपादित, कोड प्रदान करने का प्रयास करें। –

2

कोड नीचे मेरी IE7 और अन्य पर लीक नहीं करता है ब्राउज़रों:

<html> 
<head></head> 
<body> 
    <a href="javascript:" onclick="addRemove(this)">add</a> 
    <ul></ul> 
    <script> 
     function addRemove(a) { 
      var ul = document.getElementsByTagName('UL')[0], 
       li, i = 20000; 
      if (a.innerHTML === 'add') { 
       while (i--) { 
        li = document.createElement('LI'); 
        ul.appendChild(li); 
        li.innerHTML = i; 
        li.onclick = function() { 
         alert(this.innerHTML); 
        }; 
       } 
       a.innerHTML = 'remove'; 
      } else { 
       while (ul.firstChild) { 
        ul.removeChild(ul.firstChild); 
       } 
       a.innerHTML = 'add'; 
      } 
     } 
    </script> 
    </body> 
</html> 

हो सकता है आप कुछ अंतर पहचानना कोशिश कर सकते हैं आपके कोड के साथ है।
मुझे पता है कि जब आप इसे करने से पहले डीओएम में पहले नोड डालेंगे, तो आईई बहुत कम हो जाता है, उदाहरण के लिए: इसे ईवेंट संलग्न करना या innerHTML संपत्ति भरना।

13

यह वास्तविक उत्तर की तुलना में FYI अधिक है, लेकिन यह भी काफी रोचक है।

W3C डोम कोर विनिर्देश (http://www.w3.org/TR/DOM-Level-2-Core/core.html) से:

कोर डोम एपीआई तैयार कर रहे हैं सामान्य उपयोगकर्ता स्क्रिप्टिंग भाषाओं और पेशेवर प्रोग्रामर द्वारा उपयोग की जाने वाली अधिक चुनौतीपूर्ण भाषाओं सहित भाषाओं की एक विस्तृत श्रृंखला के साथ संगत होने के लिए। इस प्रकार, डीओएम एपीआई को विभिन्न प्रकार के मेमोरी मैनेजमेंट दार्शनिकों में काम करने की ज़रूरत होती है, भाषा बाइंडिंग से जो उपयोगकर्ता को मेमोरी मैनेजमेंट का खुलासा नहीं करते हैं, उन लोगों (विशेष रूप से जावा) के माध्यम से जो स्पष्ट रचनाकार प्रदान करते हैं लेकिन स्वचालित रूप से स्वचालित कचरा संग्रह तंत्र प्रदान करते हैं अप्रयुक्त स्मृति को पुनः प्राप्त करें, उन लोगों (विशेष रूप से सी/सी ++) जो आम तौर पर प्रोग्रामर को ऑब्जेक्ट मेमोरी आवंटित करने की आवश्यकता होती है, इसका उपयोग कहां ट्रैक किया जाता है, और इसे फिर से उपयोग के लिए स्पष्ट रूप से मुक्त करता है। इन प्लेटफार्मों में एक सतत एपीआई सुनिश्चित करने के लिए, डीओएम मेमोरी प्रबंधन के मुद्दों को बिल्कुल संबोधित नहीं करता है, बल्कि इसके बजाय कार्यान्वयन के लिए छोड़ देता है। डीओएम एपीआई (ईसीएमएस्क्रिप्ट और जावा के लिए) द्वारा परिभाषित स्पष्ट भाषा बाइंडिंग में से कोई भी स्मृति प्रबंधन विधियों की आवश्यकता नहीं है, लेकिन अन्य भाषाओं (विशेष रूप से सी या सी ++) के लिए डीओएम बाइंडिंग को ऐसे समर्थन की आवश्यकता हो सकती है। ये एक्सटेंशन डीओएम एपीआई को एक विशिष्ट भाषा में अनुकूलित करने वालों की ज़िम्मेदारी होगी, न कि डीओएम वर्किंग ग्रुप।

दूसरे शब्दों में: स्मृति प्रबंधन विभिन्न भाषाओं में डीओएम विनिर्देश के कार्यान्वयन के लिए छोड़ा गया है। स्मृति से किसी DOM ऑब्जेक्ट को निकालने के लिए किसी भी विधि को खोजने के लिए आपको जावास्क्रिप्ट में DOM कार्यान्वयन के दस्तावेज़ों को देखना होगा, जो हैक नहीं है। (वहाँ हालांकि उस विषय पर MDC साइट पर बहुत कम जानकारी है।)


jQuery#remove और jQuery#empty पर एक नोट के रूप में: और कुछ करता है से मैं इन तरीकों में से न तो क्या बता सकते हैं डोम से Object रों को हटाने से node या document से निकालने डोम node रों। वे केवल निश्चित रूप से यही हटाने मतलब यह नहीं है कोई स्मृति इन वस्तुओं के लिए आवंटित (भले ही वे document में अब और नहीं कर रहे हैं) नहीं है।

संपादित करें: उपर्युक्त मार्ग स्पष्ट नहीं था क्योंकि स्पष्ट रूप से jQuery चमत्कार नहीं कर सकता और उपयोग किए गए ब्राउज़र के डीओएम कार्यान्वयन के आसपास काम करता है।

+1

.remove() API: "... तत्वों के अलावा, तत्वों से जुड़े सभी बाध्य घटनाओं और jQuery डेटा को हटा दिया जाता है। डेटा और घटनाओं को हटाए बिना तत्वों को हटाने के लिए, .detach() का उपयोग करें।" – vsync

+0

आपने कहा था कि" मैं इन तरीकों में से किसी भी तरीके से नहीं बता सकता कि डोम नोड्स से ऑब्जेक्ट्स को हटाने या दस्तावेज़ से डीओएम नोड्स को हटाने के अलावा कुछ भी नहीं है ".. इसलिए मैंने एपीआई से उद्धृत किया कि यह उससे भी अधिक है। सभी बाध्य घटनाएं – vsync

+1

संदर्भ स्मृति आवंटन था। लेकिन ओह ठीक है, मैंने 'jQuery' पर मार्ग को बाहर निकाला। – FK82

1

आप करने के लिए "के बाद ठीक" रिसाव है, और अपने सभी कोड को फिर से लिखने खाते में बंद किया जाना, वृत्तीय संदर्भ आदि ले, डगलस Crockfords शुद्ध-विधि का उपयोग करने के बिना ऐसा करना चाहिए, तो नष्ट करने के लिए पहले:

http://javascript.crockford.com/memory/leak.html

या इस बंद के ठीक तरीके का उपयोग:।।

http://laurens.vd.oever.nl/weblog/items2005/closures/

+2

कृपया लिंक ठीक करें –

संबंधित मुद्दे