preface

Did everyone have a happy Chinese Valentine’s Day? Happy is good, you happy is my happy. -wuwuwu……

What’s a genius? He just put other people’s Tanabata date time, with writing on the article – Lu Xun (yes, Jiang Dong Lu Xun)

Hello everyone, I am Lin Sanxin, last I told you13 charts to beat “V8 Garbage Collection” in 20 minutesV8 garbage collection mechanism is very strong, but we can’t just create a lot of garbage to recycle, we have to minimize the amount of garbage in the development, today I will tell you how to avoid itToo much JS garbage, memory leak!

Why to avoid

What is a memory leak? It’s the fact that some of the garbage that should be recycled isn’t, and that’s what’s causing it to accumulate.

Memory leak, sounds very far away, but in fact is very close to us, we usually directly or indirectly to contact it. For example, sometimes your page, with the use of the card up, and with the extension of time, more and more card, then this time, it is necessary to consider whether the memory leak problem, memory leak is a major problem affecting the user experience, so usually through the correct code habits to avoid it, is very necessary.

How do I monitor memory

We have been emphasizing the memory memory, but it feels very unreal, at least let us see its true face?

Browser Task Manager

To open: Right-click on the top of the browser and open the Task Manager:

When opened, we see memory and JavaScript memory (in parentheses) :

  • memory: The raw memory in the page, i.eDOM nodeTotal memory usage of
  • JavaScript memory (in parentheses): is all on this pageTo objectTotal memory usage of

So what are reachable objects? Simply put: start from the pointer of the initial root object (window or global) and search down for child nodes. If the child node is found, it means that the reference object of the child node is reachable. If the reference object of the child node is not found, it means that the child node object is unreachable. Here’s an example:

// Reachable, which can be accessed through window.name
var name = 'Lin SAN Xin'

function fn () {
    // Cannot be accessed
    var name = 'Lin SAN Xin'
}
Copy the code

Back in our task management, we write a piece of code in the page:

<button id="btn"> click < / button ><script>
    document.getElementById('btn').onclick = function () {
        list = new Array(1000000)}</script>

Copy the code

Click on the front:

After clicking, I found that the memory rose instantly:

Performance

Using Chrome’s trackless mode is to avoid many other factors that can affect our viewing of memory:

Press F12 to open the debug window and select Performance

Let’s take the nuggets home page as an example! Go to Record -> Refresh Nuggets -> Stop to see the movements of the following indicators over time:

  • JS Heap: JS heap
  • Documents: the document
  • NodesDOM node:
  • Listeners: the listener
  • GPU Memory: the GPU memory

Heap snapshot

Heap snapshot, as the name implies, is to take a photo of the heap memory of a certain page and save it. The same page, before performing a certain operation, the recorded heap snapshot is one sample, may be finished, the recorded heap snapshot is another sample.

Or take the gold home page as an example, you can see that the current page memory is 13.3m, we can choose Statistics, view arrays, objects, strings and other memory

How to avoid

As mentioned above, the memory leak problem is very close to us, and we may have all caused it directly or indirectly. Here’s how to avoid this problem, which may also be a bad habit in your development.

Reduce global variables

Var, let, const (); const (); const (); const ();

document.getElementById('btn').onclick = function () {
    // A is not declared externally
    a = new Array(1000000).fill('Sunshine_Lin')} The above code is equivalent tovar a
document.getElementById('btn').onclick = function () {
    a = new Array(1000000).fill('Sunshine_Lin')}Copy the code

What’s the downside? We talked about accessibility before, and we can explain it here. If the above code is written like this, we can access the global variable a through window.a, so a is reachable, it will not be garbage collection, it will always occupy memory, not free, consumption of performance, which is against our original intention. We can verify this by taking a snapshot of the heap: record -> click the button -> record -> record -> record -> record -> record

How can it be improved? We can add the definition variable:

document.getElementById('btn').onclick = function () {
     let a = new Array(1000000).fill('Sunshine_Lin')}Copy the code

Since the local variable is unreachable, every time the function is executed, it is reclaimed and freed, so it does not occupy memory all the time. The memory before and after the click is the same:

Uncleared timer

Look at this code. In this code, after executing the fn1 function, the arR array should be reclaimed, but it is not. Why is that? Because a in the timer refers to ARR, and if the timer is not cleared, A will not be recycled. If A does not recycle, it will always refer to ARR, and arR will definitely not be recycled.

function fn() {
      let arr = new Array(1000000).fill('Sunshine_Lin')
      setInterval(() = > {
          let a = arr
     }, 1000)}document.getElementById('btn').onclick = function () {
    fn()
}
Copy the code

Performace: Record -> manual garbage collection -> connect five times button -> Manual garbage collection -> End

The first and last manual garbage collection is to compare the first and last lowest points of garbage memory, which should be the same if there is no memory leak problem. As you can see here, the amount of memory that is not collected is the amount of memory that is not collected

As it says, why is the arR array not recycled? The timer is not cleared, so a keeps referring to arR. How to solve this problem? Just clear the timer.

function fn() {
  let arr = new Array(1000000).fill('Sunshine_Lin')
  let i = 0
  let timer = setInterval(() = > {
    if (i > 5)  clearInterval(timer)
    let a = arr
    i++
  }, 1000)}document.getElementById('btn').onclick = function () {
  fn()
}
Copy the code

If we look at Performance, we find that the first two times the amount of memory is the same, which means it is normal

Use closures wisely

Let’s look at this code:

function fn1() {
    let arr = new Array(100000).fill('Sunshine_Lin')

    return arr
}
let a = []
document.getElementById('btn').onclick = function () {
    a.push(fn1())
}
Copy the code

Normally, after fn1 executes, the ARR is reclaimed, but in this case, it is not reclaimed. Why? When fn1 returns arR, then arR is pushed into array A. Array A is a global variable. Array A will not be reclaimed, so the contents of array A will not be reclaimed, so the arR will not be reclaimed. If a is not used later, then these ARRs are useless garbage. We can verify this by using Performance and heap snapshots:

Performace: Record -> manual garbage collection -> connect five times button -> Manual garbage collection -> End

The first and last manual garbage collection is to compare the first and last lowest points of garbage memory, which should be the same if there is no memory leak problem. As you can see here, the amount of memory that is not collected is the amount of memory that is not collected

Heap snapshot: First record -> connect button 5 -> Second record

You’ll notice that before and after you click, you get a lot more memory, which is the amount of memory that’s not being reclaimed

The separation of the DOM

What does it mean to separate the DOM? Or let the code speak for itself:

<button id="btn"> click < / button >let btn = document.getElementById('btn')
document.body.removeChild(btn)
Copy the code

Detached DOM = detached DOM = detached DOM = detached DOM = detached DOM = detached DOM = detached DOM = detached DOM = detached DOM = detached DOM = detached DOM = detached DOM = detached DOM = detached DOM = detached DOM = detached DOM = detached DOM = detached DOM = detached DOM

Delete the button and set BTN to NULL:

<button id="btn"> click < / button >let btn = document.getElementById('btn')
document.body.removeChild(btn)
btn = null
Copy the code

“Button” = “button”; “button” = “button”;

The resources

  • Taobao front-end is how to do optimization? How to write JavaScript efficiently? What are the actions to improve JS performance?
  • This article takes you to know how to check the memory leak caused by the page lag phenomenon

conclusion

In fact, there are more ways to avoid memory leaks than these. Here are four common ways that I hope you can avoid in your development to improve your code quality and improve your user experience.

Study group please click here, study together, fish together!!