Know about memory management in JS? What can cause a memory leak?

1. Memory life cycle

  • Memory allocation: When we declare variables, functions, and objects, the system automatically allocates memory for them
  • Memory usage: reading and writing memory, that is, using variables, functions, etc
  • Memory reclamation: The garbage collection mechanism reclaims unused memory

2. Memory allocation in JS

const n = 012; // Allocate memory to numeric variables const s = "string"; // Allocate memory to string const o = {a: 1, b: null}; // Allocate memory for objects and their contained valuesCopy the code

3. Memory usage in Js

The process of working with values is actually reading and writing to allocated memory. Reading and writing may be writing the value of a variable or an object property, or even passing the parameters of a function.

var a = 10; // Allocate memory console.log(a); // Memory usageCopy the code

Garbage collection mechanism in Js

Garbage collection algorithms rely heavily on the concept of references.

In a memory-managed environment, an object that has access to another object (implicitly or explicitly) is said to reference another object.

For example, a Javascript object has references to its stereotype (implicit references) and to its attributes (explicit references).

Here, the concept of “object” refers not only specifically to JavaScript objects, but also to function scopes (or global lexical scopes).

1. Reference count garbage collection

Reference counting algorithms define “memory out of use” simply by looking at whether an object has a reference to it. If no other object points to it, it is no longer needed.

But it has a fatal problem: circular references.

If two objects refer to each other, even though they are no longer in use, garbage collection does not collect, resulting in a memory leak.

2. Mark clearing algorithm

The tag clearing algorithm defines “no longer used object” as “unreachable object”. In simple terms, it periodically scans objects in memory from the root (in JS, global objects). Anything that can be reached from the root is still needed. Objects that cannot be reached from the root are marked as unused and recycled later.

2.1 The garbage collector will mark all variables stored in memory when running.

2.2 Clear the marks of the objects that can be touched from the root.

2.3 Variables that are still marked are considered to be ready for deletion.

2.4 Finally, the garbage collector performs the final step of memory cleaning, destroying the tagged values and reclaiming the memory they occupy.

5. Common memory leaks

1 Global variables

function foo() { bar1 = 'some text'; Bar1 this.bar2 = 'some text' // Global => window.bar2} foo();Copy the code

Uncleaned timer and callback functions

If the subsequent renderer element is removed, the entire timer actually does nothing. However, if you do not recycle the timer, the entire timer is still valid. Not only can the timer not be recycled, but also the dependencies in the timer function can not be recycled.

ServerData in this case also cannot be recycled.

var serverData = loadData(); setInterval(function() { var renderer = document.getElementById('renderer'); if(renderer) { renderer.innerHTML = JSON.stringify(serverData); }}, 5000); // call every 5 secondsCopy the code

3 the closure

In JS development, we often use closures, an inner function that has access to variables in the outer function that contains it. Closures can also cause memory leaks in the following cases

var theThing = null; var replaceThing = function () { var originalThing = theThing; Var unused = function () {if (originalThing) console.log("hi"); }; theThing = { longStr: new Array(1000000).join('*'), someMethod: function () { console.log("message"); }}; }; setInterval(replaceThing, 1000);Copy the code

This code, each time replaceThing is called, theThing gets an object containing a large array and an object for the new closure someMethod. Unused is also a closure that references originalThing.

The key to this example is that closures are shared in scope, and while unused may never be called, someMethod may be called, making it impossible to reclaim its memory. As this code is executed repeatedly, memory continues to grow.

3 DOM references

Most of the time, when we operate on the Dom, we store references to the Dom in an array or Map.

var elements = { image: document.getElementById('image') }; function doStuff() { elements.image.src = 'http://example.com/image_name.png'; } function removeImage() { document.body.removeChild(document.getElementById('image')); // At this point we still have a reference to #image, the image element, which is still not retrievable.Copy the code

In the above case, even though we removed the image element, there was still a reference to the image element, which still could not be aligned for memory reclamation

6. How to avoid memory leaks

  • Reduce unnecessary global variables and use strict patterns to avoid accidentally creating global variables.
  • Dereference (variables in closures, DOM references, timer cleanup) when you’re done with the data.
  • Organize your logic to avoid endless loops that cause your browser to freeze and crash.