Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the five common memory errors in JavaScript

2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "what are the five common memory errors in JavaScript". In daily operation, I believe many people have doubts about what the five common memory errors in JavaScript are. The editor consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful to answer the doubts about "what are the five common memory errors in JavaScript?" Next, please follow the editor to study!

JavaScript does not provide any memory management operations. Instead, memory is managed by JavaScript VM through a memory collection process called garbage collection.

Since we can't force garbage collection, how do we know it works? How much do we know about it?

Script execution is paused during this process

It frees memory for inaccessible resources

It's uncertain.

It does not check the entire memory at once, but runs in multiple cycles

It is unpredictable, but it will be executed when necessary

Does this mean you don't have to worry about resource and memory allocation? Of course not. If we are not careful, there may be some memory leaks.

What is a memory leak?

Memory leaks are allocated blocks of memory that cannot be reclaimed by the software.

Javascript provides a garbage collector, but that doesn't mean we can avoid memory leaks. In order to meet the criteria for garbage collection, the object must not be referenced elsewhere. If you hold references to unused resources, this will prevent those resources from being recycled. This is called unconscious memory retention.

Leaking memory may cause the garbage collector to run more frequently. Because this process will prevent the script from running, it may cause our program to get stuck. With such a card, picky users will surely notice that the days when the product is offline will not be over. If it is more serious, it may cause the whole application to collapse, and it will be gg.

How to prevent memory leaks? The main thing is that we should avoid retaining unnecessary resources. Let's take a look at some common scenarios.

1. Monitoring of timer

The setInterval () method repeatedly calls a function or executes a code snippet, with a fixed time delay between each call. It returns an interval ID, which uniquely identifies the interval, so you can delete it later by calling clearInterval ().

We create a component that calls a callback function to indicate that it is finished after x loops. I use React in this example, but this applies to any FE framework.

Import React, {useRef} from 'react';const Timer = ({cicles, onFinish}) = > {const currentCicles = useRef (0); setInterval () = > {if (currentCicles.current > = cicles) {onFinish (); return;} currentCicles.current++;}, 500); return (Loading...);} export default Timer

At first glance, there seems to be no problem. Don't worry, let's create another component that triggers this timer and analyze its memory performance.

Import React, {useState} from 'react';import styles from'.. / styles/Home.module.css'import Timer from'.. / components/Timer';export default function Home () {const [showTimer, setShowTimer] = useState (); const onFinish = () = > setShowTimer (false) Return ({showTimer? (): (setShowTimer (true)} > Retry)})}

After a few clicks on the Retry button, this is the result of using Chrome Dev Tools to get memory usage:

When we click the retry button, we can see that more and more memory is allocated. This indicates that the previously allocated memory has not been freed. The timer is still running instead of being replaced.

How to solve this problem? The return value of setInterval is an interval ID, which we can use to cancel this interval. In this special case, we can call clearInterval after the component has been uninstalled.

UseEffect (() = > {const intervalId = setInterval (() = > {if (currentCicles.current > = cicles) {onFinish (); return;} currentCicles.current++;}, 500); return () = > clearInterval (intervalId);}, [])

Sometimes, when writing code, it is difficult to find this problem, and the best way is to abstract the components.

React is used here, and we can wrap all this logic in a custom Hook.

Import {useEffect} from 'react';export const useTimeout = (refreshCycle = 100, callback) = > {useEffect () = > {if (refreshCycle {callback ();}, refreshCycle); return () = > clearInterval (intervalId);}, [refreshCycle, setInterval, clearInterval]);}; export default useTimeout

Now when you need to use setInterval, you can do this:

Const handleTimeout = () = >; useTimeout (100,100, handleTimeout)

Now you can use this useTimeout Hook without worrying about memory leaks, which is also the benefit of abstraction.

two。 Event monitoring

Web API provides a large number of event listeners. Earlier, we discussed setTimeout. Now take a look at addEventListener.

In this case, we create a keyboard shortcut function. Because we have different functions on different pages, we will create different shortcut key functions

Function homeShortcuts ({key}) {if (key ='E') {console.log ('edit widget')}} / / users log in on the home page and we execute document.addEventListener (' keyup', homeShortcuts) / / the user does something, and then navigates to setting function settingsShortcuts ({key}) {if (key ='E') {console.log ('edit setting')}} / / the user logs in on the home page, and we execute document.addEventListener (' keyup', settingsShortcuts)

It still looks good, except that you didn't clean up the previous addEventListener when you executed the second keyup. Instead of replacing our keyup listener, this code will add another callback. This means that when a key is pressed, it triggers two functions.

To clear the previous callback, we need to use removeEventListener:

Document.removeEventListener ('keyup', homeShortcuts)

ReFactor the above code:

Function homeShortcuts ({key}) {if (key ='E') {console.log ('edit widget')}} / / user lands on home and we executedocument.addEventListener (' keyup', homeShortcuts); / / user does some stuff and navigates to settingsfunction settingsShortcuts ({key}) {if (key ='E') {console.log ('edit setting')}} / / user lands on home and we executedocument.removeEventListener (' keyup', homeShortcuts) Document.addEventListener ('keyup', settingsShortcuts)

As a rule of thumb, you need to be careful when using tools from global objects.

3.Observers

Observers is a browser's Web API function that many developers don't know about. This is powerful if you want to check the visibility or size of the HTML element.

The IntersectionObserver interface (subordinate to IntersectionObserver API) provides a way to asynchronously observe the cross state of the target element with its ancestor element or top-level document window (viewport). Ancestor elements and windows (viewport) are called root.

Although it is very powerful, we should use it carefully. Once you have finished observing the object, remember to cancel it when you are not using it.

Look at the code:

Const ref =... const visible = (visible) = > {console.log (`It is ${visible}`);} useEffect (() = > {if (! ref) {return;} observer.current = new IntersectionObserver ((entries) = > {if (! entries [0] .isIntersecting) {visible (true);} else {visbile (false)) }, {rootMargin: `- ${header.height} px`},); observer.current.observe (ref);}, [ref])

The above code looks good. However, what happens to the observer once the component is uninstalled? It won't be erased, and the memory will leak. How can we solve this problem? Just use the disconnect method:

Const ref =... const visible = (visible) = > {console.log (`It is ${visible}`);} useEffect (() = > {if (! ref) {return;} observer.current = new IntersectionObserver ((entries) = > {if (! entries [0] .isIntersecting) {visible (true);} else {visbile (false)) }, {rootMargin: `- ${header.height} px`},); observer.current.observe (ref); return () = > observer.current?.disconnect ();}, [ref]); 4. Window Object

Adding objects to Window is a common mistake. In some scenarios, it may be difficult to find, especially when using the this keyword in the context of Window Execution. Look at the following example:

Function addElement (element) {if (! this.stack) {this.stack = {elements: []}} this.stack.elements.push (element);}

It looks harmless, but it depends on the context from which you call addElement. If you call addElement from Window Context, there will be more and more piles.

Another problem may be that a global variable is incorrectly defined:

Var a = 'example 1targets; / / scope is limited to the place where the var was created b =' example 2posts; / / added to the Window object

To prevent this problem, you can use strict mode:

"use strict"

By using strict mode, you imply to the JavaScript compiler that you want to protect yourself from these behaviors. You can still use Window when you need it. However, you have to use it in a clear way.

How strict patterns affect our previous example:

For addElement functions, this is undefined when called from the global scope

If you do not specify const | let | var on a variable, you will get the following error:

Uncaught ReferenceError: b is not defined5. Hold DOM reference

DOM nodes also cannot avoid memory leaks. We need to be careful not to save their references. Otherwise, the garbage collector will not be able to clean them up because they are still accessible.

Demonstrate with a small piece of code:

Const elements = []; const list = document.getElementById ('list'); function addElement () {/ / clean nodes list [XSS _ clean] =''; const divElement= document.createElement ('div'); const element = document.createTextNode (`adding element ${elements.length} `); divElement.appendChild (element); list.appendChild (divElement); elements.push (divElement);} document.getElementById (' addElement'). Onclick = addElement

Notice that the addElement function clears the list div and adds a new element to it as a child element. This newly created element is added to the elements array.

The next time addElement is executed, this element will be removed from the list div, but it is not suitable for garbage collection because it is stored in the elements array.

We monitor the function after several executions:

See how the node is compromised in the screenshot above. So how to solve this problem? Clearing the elements array qualifies them for garbage collection.

At this point, the study on "what are the five common memory errors in JavaScript" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report