2

I have a quick question on how garbage collection works in Javascript.

If I have this code:

var c = {name : ‘Bob’}; c = {name : ‘Mary’}; 

In the code above the variable c is pointing to the object {name : ‘Bob’}. But then I set c to point to another object in memory {name : ‘Mary’}. What will happen to the object ({name : ‘Bob’}) that c was pointing to originally? Will that original object be deallocated in memory since there are no references to it anymore?

In another case:

var c = {name : ‘Bob’}; d = c; c = {name : ‘Mary’}; 

Now, the original object that c was pointing to ({name : ‘Bob’}) would not be deallocated since d is still pointing to {name : ‘Bob’} even after "c" was changed to point to the new object: {name : ‘Mary’}. Correct?

So basically an object will not be deallocated from memory as long as there are references that are still pointing to it.

Can someone please explain to me if I am thinking about this correctly?

1
  • 2
    Yes, that's correct in principle. However, when garbage collection occurs is completely up to the browser hence the expression "is made available for garbage collection" is often used rather than "is garbage collected". Commented Oct 17, 2015 at 21:52

3 Answers 3

1

You have the right idea but there are some subtleties to be aware of:

Firstly, the JavaScript runtime decides when to actually run the garbage collection routine. Unused objects are marked for garbage collection, not immediately collected. GC can be quite expensive so it doesn't run continually.

Secondly, an object becomes eligible for GC when it becomes unreachable, rather than simply having no references.

If the GC only considered reference count you could create a "closed loop" of unreachable, uncollectible objects.

Consider this snippet:

var owner = { name: 'Ann' }; // Let's call this object 'Ann' var pet = { name: 'Zizi' }; // And this one 'Zizi' // create a loop of references owner.pet = pet; pet.owner = owner; owner = null; // owner no longer refers to Ann pet = null; // pet no longer refers to Zizi 

When this code finishes running there are no top-level references to Zizi or Ann - they are unreachable . In a modern runtime (like the one in your browser), they are marked for GC and will be cleaned up when the GC routine next runs.

But what if objects were collected only when their reference count reached zero? Let's think about Zizi. It can't be collected because Ann still has a reference to it. It can't be used, since there are no available references to it.

Ann also can't be collected because Zizi refers back to it. This is a bad situation - two objects that can't be reached by user code, but also can't be garbage collected. It's a memory leak.

This kind of garbage collection algorithm, known as reference counting, caused an infamous issue in older versions of Internet Explorer: DOM nodes and event handlers could prevent each other from ever being garbage collected. Reference-counting garbage collectors are largely obsolete for that reason.

Further reading: Chrome Devtools Docs - Memory 101.

Sign up to request clarification or add additional context in comments.

6 Comments

Hmm ok! I found the link to be a little bit confusing haha... maybe because I am not well versed with memory management, but I had one question regarding your code. When you set owner = null and pet = null, what does that line do? Does it deallocate the owner and pet objects? Also are you just referring to Bob as the owner in your example? I am not sure where bob comes from haha
I'm sorry, Bob was left over from an earlier edit! I've updated and hopefully clarified now. Assigning to null doesn't immediately deallocate the objects, but it does make them unreachable because owner and pet no longer refer to them. You couldn't write code at the end of this program that somehow gained a reference to Ann or Zizi. Because they are unreachable, they are marked for GC (in a modern runtime).
Ohh, I finally get the concept of what unreachable means! Another user @Leo Nix, posted an article that JS uses the mark and sweep algorithm instead of referencing counting which fixes the memory leak issue you referred to. Thank you for clarifying!
I actually have one more quick question haha! When you get time can you please clarify my question about the line of code where you set owner and pet to null. Since the variables owner and pet no longer refer to the objects, the objects are deallocated. But what happens to the actual variables pet and owner (not the objects {}, but the "var owner" and "var pet"). Do they get assigned to have a value of undefined like what happens in the creation phase or do these variables (var owner and var pet) not even exist in memory since they are not referencing to anything in memory?
pet and owner still exist at the end. null is a value in JavaScript (just like undefined, true, 1, "hi" and so on). At the end of this snippet owner and pet both have the value null (you could try it out in your browser's JS console). They will continue to have that value until they are assigned another value, or they go out of scope (e.g. the function they are defined in completes). At that point they will cease to exist.
|
1

Correct objects are garbage collection eventually when there are no references to them, assuming your code snippets are in the global scope this is true, of course if your var declaration is within a function it will be out of scope once the function has exited. An exception to this are closures, where objects on the local scope are still referenced by variables returned by the function.

I mentioned 'eventually' garbage collected above, because when objects are actually collected are subject to varying factors (memory pressure etc) and this is specific to the JavaScript engine (V8, chakra, nitro etc) being used.

Comments

0

MDN has a really good article regarding memory management. And it specifically discusses memory allocation and garbage collection with many examples.

3 Comments

Oh that definitely cleared up a lot. I just have a quick questions: under the Limitation: cycles header in that function each object references each other. If we use the mark and sweep algorithm after return is called in that function how are "the 2 objects (o and o2) not referenced anymore by something reachable from the global object"? Is it because the execution stack of that function is deallocated?
those two variables/objects are scoped locally to the function so once the function is executed, they are no longer reachable by anything and become useless. Therefore mark and sweep is able to release them while ref counting would indicate each has been referenced once so not eligible for garbage collection.
Ahh ok! I just realized that. That you so much for the link! Helped a ton!