Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> JavaScript

Circular Reference ก่อให้เกิด Memory Leak ใน JavaScript

Circular Reference และ Memory Leak

Circular Reference: Object A Reference Object B, Object B Reference Object A กลับมาหากัน

ปัญหาในระบบ Reference Counting (เก่า/IE)

  • Ref Count ไม่เป็น 0 → ไม่ถูก GC
  • Memory Leak ถาวรจน Browser ปิด

ตัวอย่าง: DOM ↔ JS Object Circular Reference

<html> <body> <script>
  window.onload = function() {
    var obj = document.getElementById('DivElement');
    // JS Object → DOM Element
    document.getElementById('DivElement').expandoProperty = obj;
    // DOM Element → JS Object (Circular!)
    
    obj.bigData = new Array(1000).join(new Array(2000).join('x')); // 2MB+ Data
    // Memory Leak: ทั้งคู่ไม่ถูก GC แม้ Window Unload
  };
</script> </body> </html>

วิธีแก้: ตัด Circular Reference

window.onload = function() {
  var obj = document.getElementById('DivElement');
  document.getElementById('DivElement').expandoProperty = obj;
  obj.bigData = new Array(1000).join(new Array(2000).join('x'));
  
  obj = null; // ตัด Reference! ทั้งคู่กลายเป็น Unreachable → GC ได้
};

สถานการณ์ปัจจุบัน (Modern Browsers)

  • Browser ใหม่ๆ (Chrome, Firefox, Edge, Safari) ใช้ Mark-Sweep GC → Circular Reference ไม่ใช่ปัญหา
  • IE 6/7 มีปัญหา (Reference Counting สำหรับ DOM)
  • แต่ยังควรตัด Reference เพื่อ Performance และกัน Leak ใน Edge Cases

Best Practices

  • ตั้งค่า null ให้ Variable/Property ที่ไม่ใช้แล้ว
  • ใช้ removeEventListener ลบ Listener
  • หลีกเลี่ยง Expando Property บน DOM Element
  • ใช้ WeakMap/WeakSet สำหรับ Cache/Metadata