Make writing a habit together! This is the 10th day of my participation in the “Gold Digging Day New Plan · April More text Challenge”. Click here for more details.

⭐ ⭐

Topic type: comprehensive question, JavaScript

Memory management

No matter what programming language you use, there is always the concept of memory management.

Memory management includes allocating memory, reading and writing memory, and releasing memory, for example:

let name = '阿林'  // Allocate memory
console.log(name) / / read memory
name = 'lin'      / / write memory
name = null       // Free memory
Copy the code

Memory space can be divided into stack space and heap space.

Stack space is used to store raw data types and fixed size values.

The heap space is used to store reference types. The size of the memory space is not fixed.

Look at the following legend to see how variables in JS are stored in memory.

let name = 'lin'
let age = 18
let arr = [1.2.3]
let obj = {
  xxx: 123
}
Copy the code

The behavior of allocating and reading memory is fairly consistent across many languages, but the behavior of freeing memory varies from language to language.

For example, JavaScript has a garbage collection mechanism that automatically manages the release of memory without the programmer having to worry about it.

However, some languages, such as C or C++, need to free the memory themselves, which is a great burden to the programmer and a source of many problems.

However, it does not mean that JS has a garbage collection mechanism. In terms of memory release, everything is ok. There are still a lot of memory leaks.

Example of memory leakage

What is a memory leak?

A memory leak is when a variable in memory is not used, but is not released, and memory is wasted.

Here are some memory leak scenarios to help you understand.

DOM elements

For example, the page has an element with the id Element.

<div id="element">test element</div>
Copy the code

References the element, assigns it to element, and then deletes it.

let element = document.getElementById('element')

function remove() {
  element.parentNode.removeChild(element)
}
Copy the code

Access the element after deletion, and the element still exists, as shown in the GIF below:

To solve this problem, we need to add Element = null to the remove method.

function remove() {
  element.parentNode.removeChild(element)
  element = null
}
Copy the code

Event listeners

When an event listener mounts an event handler inside a component, if it is not cleared when the component is destroyed, the variables or functions referenced inside the function will not be collected by the garbage collection mechanism. If the reference variable stores a large amount of data, it will consume memory and cause a large number of memory leaks.

Take the VUE component for example.

// Home.vue
data() {
  return {
    msg: 'lots of home data'}}created() {
  window.addEventListener('resize'.this.resizeCallback)
}
methods: {
  resizeCallback() {
    console.log('resize --> use'.this.msg)
  }
}
Copy the code

The home component has been destroyed, but the listening methods and data on the home component are still accessible, as shown in the GIF below:

The solution to this problem is as simple as removing event listeners when the component is destroyed:

beforeDestroy() {
  window.removeEventListener('resize'.this.resizeCallback)
},
Copy the code

The timer

Timers are the same as event listeners, so remember to clear timers at the right time.

data() {
  return {
    msg: 'lots of home data'.timer: null}}created() {
  this.timer = setInterval(this.intervalCallback, 500)}beforeDestroy() {
  clearInterval(this.timer)
},
methods: {
  intervalCallback() {
    console.log('setInterval --> use'.this.msg)
  }
}
Copy the code

The global variable

The garbage collection mechanism does not collect global variables, which have to be cleaned manually after they are used.

Try not to mount a large amount of data on a global variable, and if you have to do so, remember to remove it manually when you are done using it.

window.testArr = new Array(1000000).fill('xxx')

// do something

window.testArr = null
Copy the code

There are some cases where variables can be mounted to Windows, which should be avoided in real projects using lint, such as:

function fn() {
  foo = '123'       // Declare variables directly
  this.bar = 'qwe'  // Assign the variable to this, which refers to the window
}
fn()
Copy the code

closure

Closures have the property of creating long-lived variables in functions. Abusing closures to store large amounts of data is a waste of memory.

For closure, see my article:

Tell us what you understand about closures

At the end

Alin level is limited, the article if there are mistakes or improper expression of the place, very welcome to point out in the comment area, thanks ~

If my article is helpful to you, your 👍 is my biggest support ^_^

You can also follow the front End Daily Question column in case you lose contact

I’m Allyn, export insight technology, goodbye!

The last:

Open a random website and count the total number of tags used on that website

Next up:

Front End Daily Question (48) How does the front end troubleshoot memory leaks