JavaScript Memory Management: The Secret to a Clean and Fast App
Rahul Vijayvergiya
Posted on August 20, 2024
This post was initially published on my blog. Check out the original source using the link below:
Ever wonder how JavaScript keeps our web apps running smoothly without turning user's computer into a digital hoarder’s house. All thanks to memory management and garbage collection. Think of it as a digital housekeeper that clean up behind the scenes. In this blog, we’ll dive into how JavaScript handles memory, why garbage collection matters, and how can we avoid the memory leaks which can make our app sluggish.
1. Memory Allocation: Where Does All the Stuff Go?
When we write code in JavaScript, memory allocation happens automatically. Imagine we’re moving into a new house. We’ve got boxes labeled "Clothes," "Kitchen Stuff," and "Random Things that Should be Probably Throw Away." When we unpack, we need to find places for everything. In JavaScript, memory allocation is a bit like unpacking those boxes. There are three main scenarios where memory gets allocated:
Variables: When we declare a variable, JavaScript allocates memory to store its value. They are like socks and need a drawer to live in.
Objects and arrays : Creating objects and arrays also requires memory allocation for storing data. They are like our kitchen appliances which take up more space and need proper storage.
Functions: Memory is allocated when we define and execute functions. They are recipes, we pull them out when we need them, and then put them away once no longer needed.
let name = "Cookie Monster"; // Memory drawer for the string "Cookie Monster"
let snacks = ["cookies", "more cookies", "even more cookies"]; // A pantry for the array of snacks
function eatSnack() {
console.log("Om nom nom"); // A recipe for snacking
}
We don’t have to manually manage this memory—JavaScript does it for us. Just like how we wouldn’t leave our toaster in the living room, JavaScript makes sure everything’s in its place so our code can run smoothly.
2. Javascript Memory Life Cycle: Use It and Lose It
The life cycle of memory in JavaScript is like borrowing stuff from a friend. First, we take it (allocate memory), then use it (run our code), and finally, (should) give it back (release memory). If we forget to give things back, well, that’s when the trouble starts :)
Memory in JavaScript goes through a simple life cycle:
Allocation: When we create a variable, object, or function, memory is allocated.
Usage: This allocated memory is used to store values and execute code.
Release: When no longer needed, it should be released to make room for new data.
JavaScript tries to be a good friend by automatically cleaning up after we are done through garbage collection.
3. What is Garbage Collection?
Garbage collection is the process of identifying and freeing up memory that is no longer in use. JavaScript’s garbage collector automatically removes data that our program no longer needs to prevent memory leaks.
In a way its Javascript's Marie Kondo ;) that cleanup and organise things we don’t need anymore. It finds all the things we’ve left lying around that don’t "spark fun" (a.k.a. aren’t being used) and gets rid of them to free up space.
Mark-and-Sweep Algorithm
The garbage collector uses something called the Mark-and-Sweep algorithm.
Marking: The garbage collector starts by marking all the objects that are still reachable from the root (e.g., the global object or variables still in use). Just like the cleaner who first goes through entire house, marking everything that’s still useful ( favourite mug, that shirt we wear all the time).
Sweeping: It then identifies objects that are not marked, meaning they’re no longer reachable, and removes them from memory. Just like a cleaner sweeps up everything we don’t need and gets rid of it.
function createSnack() {
let snack = {
type: "cookie",
flavor: "chocolate chip"
};
return snack;
}
let snack1 = createSnack();
let snack2 = createSnack();
// When we finish the first snack, it's time to get rid of the crumbs (memory).
snack1 = null;
In this example, once when snack1
is set to null
, JavaScript’s knows we’re done with it and sweeps it away.
4. Memory Leaks: When Our House Starts to Overflow
If we keep holding onto stuff we don’t need, our house (memory) gets cluttered. The same way despite automatic garbage collection, memory leaks can still happen when references to unused objects persist. Here are some common scenarios that lead to memory leaks:
- Global Variables: The Socks Under the Bed
Global variables stay in memory for the entire life of the application. They are like those socks that keep disappearing under the bed. They stay forever and take up space we didn’t even know.
function messyFunction() {
forgottenSocks = "These are now global"; // Whoops, no 'let', 'const', or 'var'—now it's everywhere!
}
- Unintended Closures: The Forgotten Sandwich
With Closures, an inner function retains access to variables from an outer function, even after the outer function has finished execution. It's like that sandwich we accidentally left in our backpack.
function outerFunction() {
let bigSecret = "This is a huge secret no one needs to know anymore";
return function innerFunction() {
console.log(bigSecret); // Why are we still holding onto this?
};
}
let inner = outerFunction(); // The big secret is still around, cluttering up memory.
- Event Listeners: The Party Guests Who Never Leave
If we add event listeners but don’t remove them when they’re no longer needed, they can cause memory leaks because they keep references to elements that may have been removed from the DOM. Think of it like guests who refuse to go home after the party. We need to tell them it’s time to leave, or they’ll keep eating our snacks :D
let button = document.getElementById("partyButton");
button.addEventListener("click", function() {
console.log("Party time!");
});
// If the button disappears, tell our guests to go home.
button.removeEventListener("click", partyTime);
- Detached DOM Elements: The Floating Ball in pool after party
DOM elements that are removed from the document but still referenced in our JavaScript code will not be garbage collected, leading to memory leaks.
let ball = document.getElementById("myChair");
document.body.removeChild(ball); // The ball is still in memory, just floating around!
5. Best Practices to Keep The Code Clean
Always declare variables (use
let
,const
, orvar
) to avoid creating global variables.Clean up event listeners when they are no longer needed, especially if the elements they were attached to are removed, so our guests don’t overstay.
Watch out for closures that hold onto unnecessary secrets.
Use weak references (
WeakMap
,WeakSet
) when we can—they won’t stop the garbage collector from doing its thing.Manually nullify references to things (object, variable) we don’t need anymore, so our house doesn’t overflow.
Conclusion: Keep It Clean, Keep It Fun
JavaScript’s memory management is like having a good friend who helps us stay organised. But even the best of friends need some guidance. By being mindful and following some simple practices, we can keep our app running smoothly and prevent it from turning into a hoarder’s house. So lets declutter code and enjoy a clean, efficient app!
References
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_management
https://www.turing.com/kb/handling-memory-management-in-javascript
https://www.calibraint.com/blog/garbage-collection-in-javascript
https://www.geeksforgeeks.org/mark-and-sweep-garbage-collection-algorithm/
https://www.tutorialspoint.com/explain-in-detail-about-mark-and-sweep-algorithm-in-javascript
Posted on August 20, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.