An interesting read indeed!
So to answer your question regarding your fixed version, it basically does nothing different. You can say that it is the exact same as your ‘unfixed’ version, hence no change in garbage collection.
In this example, the key problem that was explained in the article was that unused
has a reference to theThing
.
I’ll quote it here again from the blog post:
At the same time, the variable unused
holds a closure that has a reference to originalThing
( theThing
from the previous call to replaceThing
)
That’s not obvious at a first glance, because clearly, the unused
function uses originalThing
, not theThing
.
Answer to this is references
.
In Javascript, if you assign an object to a variable, a new copy of the object will not be created, but a reference
to the object is stored.
For example:
// Make a simple person object
var personOne = {
name: 'Alex',
age: 45
};
// Assign it to different variable
var personTwo = personOne;
At this point, we have created an object and then assigned it to another variable.
If you console.log
both variables, you’ll get the same output.
Now we will change the name of personTwo
:
// Just changing the name, nothing much
personTwo.name = 'Mark'
Now, if you console.log
, what do you expect the output? If you’re not 100% sure, please first try logging this in your browser developer console to see this in action and teach this yourself.
Here is the spoiler:
console.log(personTwo)
// Output: { name: 'Mark', age: 45 }
// The fun part!
console.log(personeOne)
// Output: { name: 'Mark', age: 45 }
You may ask… but why? We didn’t change the personOne
’s name.
We did actually. Again, because of reference
.
Here’s the breakdown:
- First we created a brand new object and stored in a variable.
- Then we made a new REFERENCE to that object in a variable.
Note that, we did not create a new object. We only created a new variable that points to the same object in memory.
- Then we changed the name of that object using the second variable. (Again, we only had one object and we changed it its property)
- Then we logged it, and sure enough, that object’s
name
property was changed in the memory, that’s why it reflected on both variable references, we though we changed on only one variable.
Now back to your question. Here is the breakdown of the unfixed/fixed version (they’re same):
The very first time replaceThing
is called, these things happen:
originalThing
becomes null
as well, since theThing
is null
unused
function uses originalThing
which is null
.
- we create a new object and assign it to
theThing
The second time it runs, these things happen:
- We assign
originalThing
to theThing
and now originalThing
is a reference
to the same object as theThing
is.
unused
function uses originalThing
, again, which is an existing object which also contains someMethod
as well.
- we create a new object and assign it to
theThing
.
(The previous object is still stored in originalThing
though, it is still in use. It will be reassigned on next setInterval
execution)
And the same thing goes on and on.
(And in your ‘fixed’ version, it does nothing, except assigning theThing
to a new object, which we were already doing previously. It is also IIFE
so it is not adding any further memory leaks)
So hopefully, now you can see how someMethod
is still in scope in unused
function and is causing preventing the garbage collector free the memory.
I’d say that read the blog post again, it explains in a better way than I could. I only tried to explain why your fixed version doesn’t do anything.
And also be sure to read the blog post on the Meteor page, which is also linked in the above article. It goes into way more detailed explanation of the exact problem and using the same example.
A side note: Google for Javascript primitive values vs reference values
etc and you’ll find a bunch of resources that cover this topic in detail.
And also, get to know which types are references and which are values so you’ll also be able to spot these things in the future.