This is the fifth day of my participation in the August More text Challenge. For details, see:August is more challenging

This article is a browser-specific JavaScript script, node.js is pretty much the same, and there is no node.js scenario involved here. Of course, as a server-side language, Node.js is inevitably more concerned with memory leaks.

Users generally do not spend too much time on a Web page, and even if there is a small memory leak, reload page memory will be freed. Moreover, browsers also have an automatic memory recycling mechanism, so memory leaks are not particularly concerned.

However, as developers, if we have no concept of memory leaks, sometimes there is still a memory leak, resulting in page jam. Knowing about memory leaks, knowing how to avoid memory leaks, is the only way to improve our front-end skills.


Concept of memory

Life cycle of memory

How do memory leaks occur

A memory leak scenario

How do I find a memory leak

Concept of memory

Memory is one of the most important components in computer, it is the bridge of communication with CPU. All programs in a computer are run in memory, so the performance of memory has a great impact on the computer. Memory, also known as internal storage, is used to temporarily store computing data in the CPU and to exchange data with external storage, such as the hard disk. As long as the computer is running, the CPU will transfer the data needed to be calculated to the memory for calculation. When the calculation is completed, the CPU will send the results. The memory operation also determines the stable operation of the computer. Memory is composed of memory chip, circuit board, goldfinger, etc.

Life cycle of memory

Memory also has a life cycle, no matter what the programming language, can be generally divided into three cycles in order:

  • Distribution period

    Allocate the required memory

  • life

    Use allocated memory (read, write)

  • Release period

    Release and return them when they are no longer needed

Memory allocation -> Memory Usage -> Memory release.

How do memory leaks occur

A memory leak scenario

How do I find a memory leak

What is a memory leak?

In computer science, a memory leak is a failure by a program, due to negligence or error, to free memory that is no longer in use. A memory leak is not a physical disappearance of memory, but a waste of memory when an application allocates memory and loses control of that memory before releasing it due to design errors.

If there is no release period of the life cycle when memory is not needed, then there is a memory leak.

Memory leak simple understanding: useless memory is still occupied, can not be released and returned. In severe cases, unused memory will continue to increase, causing the entire system to stall or even crash.

JavaScript memory management mechanism

Low-level languages like C typically have low-level memory management interfaces, such as malloc() and free(). In contrast, JavaScript automatically allocates memory when variables (objects, strings, etc.) are created and “automatically” frees them when they are not used. The process of freeing is called garbage collection. This “automatism” is a source of confusion and gives JavaScript (and other high-level languages) developers the false sense that they can afford not to care about memory management.

JavaScript memory management mechanisms correspond to the life cycle of memory one to one. First you need to allocate memory, then use it, and finally free it.

The JavaScript language does not require the programmer to manually allocate memory, and in most cases does not require the programmer to manually free memory. For JavaScript programmers, it usually means using memory (that is, using variables, functions, objects, etc.).

Memory allocation

JavaScript defines variables to automatically allocate memory. Suffice it to say that JavaScript memory is automatically allocated.

Consider an example of automatic memory allocation:

// Let number = 123; Const string = "xianshannan"; Const object = {a: 1, b: null}; Const array = [1, null, "abra"]; Function func(a){return a; }Copy the code

Memory usage

The process of using a value is actually reading and writing to the allocated memory. Reading and writing can be writing the value of a variable or an object property, or even passing a function parameter.

Following the memory allocation example above, let’s continue with the memory usage example:

// Write memory number = 234; // Read the memory of number and func, write the memory of func parameter func(number);Copy the code

Memory recovery

Garbage Collection (GC) is commonly referred to as Garbage Collection in the front-end boundary.

Memory leaks generally occur in this step. Although the memory collection mechanism of JavaScript can reclaim most of the garbage memory, there are still cases that can not be reclaimed. If there are these cases, we need to manually clean up the memory.

In the past, some older versions of the browser JavaScript recycling mechanism is not so perfect, often some bug memory leaks, but today’s browser is basically not these problems, the knowledge of the outdated here will not do the deep.

Here’s a look at the current JavaScript garbage memory collection of two ways, familiar with the two algorithms can help us understand some memory leakage scenarios.

Reference counting garbage collection

This is the most rudimentary garbage collection algorithm. This algorithm simplifies the definition of “is the object no longer needed” to “has the object been referenced by other objects”. If there is no reference to the object (zero reference), the object is collected by the garbage collection mechanism.

In the following example, is the memory of “this object” reclaimed?

Var a = {a: 1, b: 2,} var b = {a: 1, b: 2,} // Now, the original reference of "this object" is replaced by b, a = 1;Copy the code

In the current execution environment, if the memory of “this object” has not been reclaimed, you need to manually release the memory of “this object” (of course, it has not left the execution environment). For example:

b = null; // or b = 1, but replace "this object"Copy the code

The memory of the “object” is thus reclaimed.

ES6 distinguishes between strong references and weak references, which are currently only available in sets and maps.

Only objects with a reference count of 0 will have their memory reclaimed, so you usually need to reclaim memory manually (if you haven’t done the marker cleanup yet and you’re still in the current execution environment).

Weak references, however, do not trigger reference count stacking. As long as the reference count is zero, the weak reference automatically disappears without manual memory reclamation.

Mark clearance

Variables are marked “in” when they enter the execution environment and “out” when they leave the execution environment. Variables marked “in” cannot be reclaimed because they are in use, while variables marked “out” can be reclaimed

The environment can be thought of as our scope, but variables in the global scope are only destroyed when the page closes.

Var b = 2; var b = 2; function test() { var a = 1; Return a + b; // Return a + b; } // When the function is finished, a is marked out of the environment and is reclaimed // but b is not marked out of the environment test();Copy the code

Some scenarios of JavaScript memory leaks

JavaScript’s memory collection mechanism can recycle most of the garbage memory, but there are still cases that can not be recycled. The programmer wants to make the browser memory leak, the browser also can’t control.

The following examples are in the execution environment, not leaving the current execution environment, and have not triggered the tag clearance. So you need to understand the above JavaScript recycling mechanism to understand the following scenario.

Unexpected global variables

Function count(number) {// basicCount = window.basiccount = 2; basicCount = 2; return basicCount + number; }Copy the code

However, with the help of ESLint, this scenario is almost impossible to do now, and ESLint will simply report an error, just so you know.

The forgotten timer

Forgetting to clean up is one of the most common beginner mistakes.

Take a vue component as an example.

<template> <div></div> </template> <script> export default { methods: </script> </script> </script> </script>Copy the code

The setInterval is still running when the component is destroyed. The memory involved in the setInterval cannot be reclaimed (the browser will consider this required memory, not garbage memory). The timer needs to be cleared when the component is destroyed, as follows:

<template> <div></div> </template> <script> export default { methods: },}, mounted() {this.refreshInterval = setInterval() {this.refreshInterval = setInterval() {this.refresh()}, 2000) }, beforeDestroy() { clearInterval(this.refreshInterval) }, } </script>Copy the code

Forgotten event listeners

Forgetting to clean up useless event listeners is one of the most common mistakes beginners make.

Continue to use the vue component as an example.

<template> <div></div> </template> <script> export default { mounted() { window.addEventListener('resize', () => {// do something here})},} </script>Copy the code

When the component is destroyed, the resize event is still listening, and the memory involved is not recollected (the browser will consider this to be necessary memory, not garbage memory), so the related events need to be removed when the component is destroyed, as follows:

<template> <div></div> </template> <script> export default {mounted() {this.resizeEventCallback = () => {// do something here}  window.addEventListener('resize', this.resizeEventCallback) }, beforeDestroy() { window.removeEventListener('resize', this.resizeEventCallback) }, } </script>Copy the code

If there are any mistakes in this article, please feel free to correct them in the comments section. If this article has helped you, please like 👍 and follow 😊.