Talk about lexical scope in JS

There is only lexical scope in JS, which means that scope is defined at definition time and not at execution time. Such as:

var value = 1; function foo() { console.log(value); } function bar() { var value = 2; foo(); } bar(); <br>//1Copy the code

Garbage collection and memory leaks in JavaScript

Javascript has automatic Garbage Collecation.

The mechanics of JavaScript garbage collection are simple: It finds variables that are no longer used, and the garbage collector periodically executes them at regular intervals.

Var a = "float on the waves "; Var b = "front-end craftsman "; var a = b; / / rewrite aCopy the code

When the system detects the fact that the string has lost its reference, it frees up the string’s storage space so that it can be reused.

There are two methods of garbage collection: tag scavenging and reference counting. Reference counting is less common, and tag clearing is more common.

Tag scavenging is the most common method of garbage collection in javascript. When a variable enters the execution environment, it is marked as “enter environment”. You can never free up memory occupied by variables that enter the environment. When a variable leaves the environment, it is marked “out of the environment.” At last. Garbage collectors clean up memory and reclaim the memory space they occupy.

Var m = 0,n = 19 var m = 0,n = 19 Add (m, n) // Mark a, B, and c as entering the environment. Console. log(n) // A, B, and C are marked as leaving the environment and waiting for garbage collection. function add(a, b) { a++ var c = a + b return c }Copy the code

Reference counting refers to the fact that the language engine has a “reference table” that holds the number of references to all resources (usually values) in memory. If the number of references to a value is zero, the value is no longer needed, so it can be freed.

var arr = [1, 2, 3, 4]; Arr = [2, 4, 5] console.log(' float in the stream ');Copy the code

If the array [1, 2, 3, 4] references arr to another value, then the number of references to the array [1, 2, 3, 4] is reduced by 1. If the number of references to the array [1, 2, 3, 4] becomes 0, then there is no way to access the value, so the memory space can be reclaimed.

But reference counting has one of the biggest problems: circular references

function func() { let obj1 = {}; let obj2 = {}; obj1.a = obj2; // obj1 references obj2 obj2.a = obj1; // obj2 references obj1}Copy the code

To solve the problem of circular references, it is best to manually set them to null when they are not in use. The above example could do this:

obj1 = null;
obj2 = null;
Copy the code

What can cause a memory leak?

1. Global variables

function fo(arg) { bar = "this is a hidden global variable"; } function foo() { this.variable = "potential accidental global"; } // foo calls itself, this refers to the global object (window) foo();Copy the code

Global variables that are not released until the page is closed.

Add ‘use strict’ to the header of your JavaScript file to avoid this type of error. Enable strict schema parsing JavaScript to avoid unexpected global variables.

2. Forgotten timers or callback functions

var someResource = getData(); setInterval(function() { var node = document.getElementById('Node'); If (node) {// Process node and someResource node.innerhtml = json.stringify (someResource)); }}, 1000);Copy the code

When the DOM is removed, the timer will still exist, and since the callback contains a reference to the someResource, the someResource outside the timer will not be released.

3. No DOM element references are cleaned

Sometimes it is useful to save the internal data structure of a DOM node. If you want to quickly update several rows of a table, it makes sense to store each DOM row as a dictionary (JSON key-value pairs) or an array. At this point, there are two references to the same DOM element: one in the DOM tree and one in the dictionary. If you decide to delete these rows in the future, you will need to remove both references.

var elements = { button: document.getElementById('button'), image: document.getElementById('image'), text: document.getElementById('text') }; function doStuff() { image.src = 'http://some.url/image'; button.click(); console.log(text.innerHTML); } function removeButton() { document.body.removeChild(document.getElementById('button')); // At this point, there is still a global #button reference // elements dictionary. The button element is still in memory and cannot be collected by GC. }Copy the code

Although we removed the button with removeChild, the #button reference is still stored in elements, in other words, the DOM element is still in memory.

4. The closure

function bindEvent(){
  var obj=document.createElement('xxx')
  obj.onclick=function(){
    // Even if it is a empty function
  }
}
Copy the code

Closures can hold local variables in a function without freeing them. When the event callback is defined in the above example, it forms a closure because the function is defined within the function and the inner function-the event callback refers to an external variable.

Function bindEvent() {var obj = document.createElement(' XXX ') obj.onclick = onclickHandler} // Or in an external function that defines an event handler, Function bindEvent() {var obj = document.createElement(' XXX ') obj.onclick = function() {// Even if it is a empty function } obj = null }Copy the code

Optimization of garbage collection usage scenarios

1. Array array optimization

const arr = [1, 2, 3, 4]; Console. log(' boat on the wave '); Arr. Length = 0 // Can be cleared directly, and the array type remains unchanged. // arr = []; We made the a variable an empty array, but we reapplied an empty array object on the heap.Copy the code

2. Function expression/object in the loop, can reuse the best outside the loop. Unused function expressions/objects should be set to NULL as soon as possible and will be garbage collected as soon as possible.