Memory management - Garbage Collector in JS
Isn’t it fascinating how we use language all the time, but some of the “behind-the-scenes” stuff just poof disappears from our minds? Like, I don’t know if it’s the same for you guys, but I totally catch myself forgetting the basics sometimes. Anyone else feel this? Or is it just me? 😅
I’m mentioning this because the other day, I was reading a blog post about memory management and garbage collectors, and the author casually mentioned that JavaScript has its own garbage collector. And even though I knew that, I found myself genuinely surprised! I guess it’s just one of those things that’s always been there, but I’d never really thought about it in depth. Just kinda one of those things you gloss over, I think. 😅
I don’t know why, but whenever I hear about Garbage Collectors, the first language that pops into my head is Go. Maybe it’s because JS and Go were the first languages I started learning, and I don’t know much about others yet—but that’s just where my mind goes!
In JavaScript, the garbage collector automatically frees up memory occupied by objects that are no longer referenced or reachable. This helps prevent memory leaks and reduces the risk of crashes.
JavaScript's garbage collector uses a mark-and-sweep algorithm to identify objects that are no longer referenced. When an object is created, it gets marked, and if the mark can't reach the object anymore (because nothing references it), it gets swept away (its memory is freed).
However, while the mark-and-sweep algorithm is commonly linked to JavaScript’s garbage collection, it’s essential to recognize that each JavaScript engine—like V8 in Chrome, SpiderMonkey in Firefox, and JavaScriptCore in Apple products—might implement its own variations or additional optimizations. For example, some engines use generational garbage collection, which improves performance by separating objects based on their lifespan.
So, while mark-and-sweep provides a foundational approach, the specific implementation can differ across engines, making it challenging to generalize JavaScript’s garbage collection behavior universally.
So imagine you have a JavaScript application running in the browser, and it uses a lot of memory. The garbage collector will periodically run to free up that memory, so your application stays responsive. JavaScript's GC runs on the main thread (not a hard rule across all environments or implementations), which can lead to some performance issues if not handled properly.
That said, at this point, if you’re just starting out like me, you might be thinking, “Wait, what the heck is mark-and-sweep?”
Mark-and-sweep is a garbage collection algorithm that identifies which objects in memory are still referenced and which aren't. The "mark" phase goes through all objects and marks the ones that are reachable from roots (like global variables). The "sweep" phase goes through all objects and frees up memory for the ones that weren't marked. This algorithm helps prevent memory leaks and keeps the application running smoothly.
It starts by identifying all the "roots" in memory - basically anything that can be directly accessed, like global variables or values on the call stack. Then it scans the entire heap and follows all references from those roots to see what other objects they point to. Any object reachable from those roots gets marked as alive. After marking everything, the sweeper comes along and looks at every object in memory.
For context, imagine an object person that references objects address and phone . If person gets marked, then address and phone will get marked too because they're referenced by person . If address references another object city, then city will get marked as well because it's reachable from address. That's basically how mark-and-sweep works.
So, in JavaScript, when an object is created with let obj = { foo: 'bar' }; , the garbage collector will free up the memory when obj is no longer referenced. But what about closures? Like in function closure() { return function inner() { console.log('Hello'); }; } ? The garbage collector will still collect these variables, even though they're referenced somewhere.
Closures in JavaScript could easily fill an entire post on their own from a beginner’s perspective—they definitely add some complexity! I’ve learned that closures keep references to variables even after the outer function has finished running. When you create a closure, the inner function “remembers” variables from the scope it was created in. This means that, even if the outer function is done, those variables don’t get garbage-collected right away because the closure is still holding onto them. So, closures make garbage collection a bit trickier, as they keep variables alive longer than we might expect.
Not to mention, closures can lead to memory leaks if we’re not careful. Since they hold onto variables even after the outer function is done, they can keep large objects or data structures in memory longer than necessary. If we accidentally keep a reference to a closure (like in a long-running app or a single-page app), all those “remembered” variables stick around too. So, while closures are super powerful, it’s good to watch out for how they’re used to avoid unnecessary memory use.
Conclusion
JavaScript has had a garbage collector since its early days, but it works differently due to JavaScript's event-driven, single-threaded nature. Instead of running continuously, JS’s garbage collector performs periodic "mark-and-sweep" operations. This approach is tuned to work well with the non-blocking, asynchronous style of JavaScript, where long pauses for garbage collection could disrupt performance.
For reference:
https://javascript.info/garbage-collection
https://felixgerschau.com/javascript-memory-management/#:~:text=In%20JavaScript%2C%20when%20we%20create,be%20used%20for%20another%20purpose.
https://dev.to/ankitparte80/js-memory-management-3h51
Happiest when writing code, mentoring, managing – in that order
9moGreat article, thanks! I think it's worth noting that you should avoid having global variables at all
Full Stack developer | content creator| open for collabs| freelancer
9moGreat share 💻 Alcione F. Ribeiro