Introduction
Low-level languages, such as C, have low-level memory management primitives, such as malloc() and free(). JavaScript's memory primitives, on the other hand, are allocated when variables (objects, strings, etc.) are created and then "automatically" freed when they are no longer in use. The latter is called garbage collection. This "automatic" is obfuscating and giving JavaScript (and other high-level languages) developers an illusion: they can ignore memory management.
Memory life cycle
No matter what programming language, the memory life cycle is basically the same:
1. Allocate the memory you need
2. Use it (read, write)
3. Release ps: and "put the elephant in the refrigerator" means the same
The first and second parts of the process are clear in all languages. The last step is clear in low-level languages, but in high-level languages like JavaScript, the last step is not clear.
Memory allocation for JavaScript
Variable initialization
In order not to bother programmers with the problem of allocation, JavaScript completes memory allocation when defining variables.
The code copy is as follows:
var n = 123; // Allocate memory to numeric variables
var s = "azerty"; // Give character type
var o = {
a: 1,
b: null
}; // Allocate memory for objects and their contained variables
var a = [1, null, "bra"]; // Allocate memory for arrays and their contain variables (like objects)
function f(a){
return a + 2;
} // Allocate memory for functions (callable objects)
// Function expressions can also assign an object
someElement.addEventListener('click', function(){
someElement.style.backgroundColor = 'blue';
}, false);
Memory allocation through function calls
Some function calls result in allocating object memory:
The code copy is as follows:
var d = new Date();
var e = document.createElement('div'); //Assign a DOM element
Some methods assign new variables or new objects:
The code copy is as follows:
var s = "azerty";
var s2 = s.substr(0, 3); // s2 is a new string
//Because string is an invariant, JavaScript may not allocate memory, but it only stores the range 0-3.
var a = ["ouais ouais", "nan nan"];
var a2 = ["generation", "nan nan"];
var a3 = a.concat(a2); // There are four elements in the new array that join the array a and array a2.
Use of values
The process of using values is actually a read and write operation of allocating memory, which means that a variable or an object's property value can be written, or even the parameters of a function can be passed.
Freed when memory is no longer needed
Most memory management problems are at this stage. The hardest task here is to find "the allocated memory is indeed no longer needed." It often requires developers to determine which piece of memory in the program is no longer needed and free it.
The high-level language interpreter is embedded with a "garbage collector" and its main job is to track the allocation and use of memory so that it will be automatically released when the allocated memory is no longer in use. This process is an approximation because it is impossible to determine whether a certain piece of memory needs to be determined (it cannot be solved by some algorithm).
Garbage recycling
As mentioned above, the question of automatically looking for whether some memory is "no longer needed" is impossible to determine. Therefore, the implementation of garbage collection can only solve general problems with limitations. This section will explain the necessary concepts to understand the main garbage collection algorithms and their limitations.
Quote
Garbage collection algorithms mainly rely on the concept of reference. In a memory-managed environment, if an object has permission to access another object (implicitly or explicitly), it is called an object referring to another object. For example, a Javascript object has a reference to its prototype (implicit reference) and a reference to its properties (explicit reference).
Here, the concept of "object" not only special Javascript objects, but also function scope (or global lexical scope).
Reference count garbage collection
This is the easiest garbage collection algorithm. This algorithm simplifies "whether the object is no longer needed" as "whether the object has other objects referenced to it". If no reference points to the object (zero reference), the object will be recycled by the garbage collection mechanism.
For example
The code copy is as follows:
var o = {
a: {
b:2
}
};
// Two objects are created, one is referenced as the other's attribute, and the other is assigned to the variable o
// Obviously, none of them can be collected by garbage
var o2 = o; // The o2 variable is the second reference to "this object"
o = 1; // Now, the original reference o of "this object" is replaced by o2
var oa = o2.a; // Reference the a property of "this object"
// Now, there are two references to "this object", one is o2 and the other is oa
o2 = "yo"; // The original object is now zero reference
// He can be recycled
// However, the object of its property a is still referenced by oa, so it cannot be recycled yet
oa = null; // The object with the a property is now also referenced by zero
// It can be garbage collected
Limitation: Recycle reference
This simple algorithm has a limitation that if an object refers to another (forming a circular reference), they may "no longer need it", but they will not be recycled.
The code copy is as follows:
function f(){
var o = {};
var o2 = {};
oa = o2; // o Reference o2
o2.a = o; // o2 quotes o
return "azerty";
}
f();
// Two objects are created and referenced to each other, forming a loop
// They will not leave the scope of the function after being called
// So they are useless and can be recycled
// However, the reference counting algorithm takes into account that they have references to each other at least once, so they will not be recycled
Practical examples
IE 6, 7 Recycling of reference counting on DOM objects. A common problem for them is memory leaks:
The code copy is as follows:
var div = document.createElement("div");
div.onclick = function(){
doSomething();
};
// div has a reference pointing to the event processing property onclick
// Event handling also has a reference to the div that can be accessed in the function scope
// This circular reference will cause both objects to be garbage collected
Mark-clearing algorithm
This algorithm simplifies "whether the object is no longer needed" as "whether the object is available".
This algorithm assumes setting an object called root (in Javascript, root is a global object). Regularly, the garbage collector will start at the root, find all objects referenced from the root, and then find the objects referenced by these objects... Starting from the root, the garbage collector will find all objects that can be obtained and all objects that cannot be obtained.
This algorithm is better than the previous one, because "objects with zero references" are always unavailable, but on the contrary, it is not necessarily true, refer to "circular references".
Since 2012, all modern browsers have used the tag-clean garbage collection algorithm. All improvements to the JavaScript garbage collection algorithm are based on improvements to the tag-cleaning algorithm, without improving the tag-cleaning algorithm itself and its simplified definition of whether the object is no longer needed.
Circular references are no longer a problem
In the example above, after the function call returns, both objects cannot be retrieved from the global object. Therefore, they will be recycled by the garbage collector.
The second example also, once the div and its event processing cannot be retrieved from the root, they will be recycled by the garbage collector.
Limitation: Objects need to be explicitly unavailable
Although this is a limitation, it is rarely broken through, which is why in reality, few people care about the garbage collection mechanism.