Suppose I create two objects:
var a = new SomeObject();
var b = document.getElementById("someElement");
/* Do something with those two object */
After do something with those two objects I need to clear them in case of memory leak.
The question is which one should I choose btween "null" and "undefined" that the Garbage Collector will prefer.
// firstly, remove DOM node
b.parentElement.remove(b);
// then clear the variants using "null" or "undefined"
a = null;
b = null;
/* or:
a = undefined;
b = undefined;
*/
Any comments will be appreciated!
The garbage collector works by keeping track of which objects are reachable by your code. The idea is that if an object is not reachable, the block of memory it occupies can be freed without breaking your program.
One way in which an object can be reached is if it's assigned to a variable. Assigning a new value to a variable that presently points to an object (e.g. by assigning null to a) will reduce the reference count on that object by one. When this or any object's reference count is reduced to zero, it will qualify for garbage collection.
All that said, it's not really important what value you use to replace the value of a variable, as long as it's not some other object that would otherwise be garbage collected. For this reason, both undefined and null will work.
Note that you only need to scrub variables like this if a variable remains reachable by your code after the function that the variable was declared in returns. This could happen if an anonymous function closes on the variable, if the variable is "global" (tacked onto the global object or declared without the var keyword), or if the variable is actually a field on an object that's still reachable.
What is the proper usage of the WeakMap in JavaScript? What kind of timing issues may occur when I use it? IN particular, I am wondering what would happen in the following situation:
var wm1 = new WeakMap()
var o1 = {},
o2 = function(){},
o3 = window;
// in other method:
wm1.set(o1, 37);
wm1.set(o2, "azerty");
if (wm1.has(o2)) {
//Garbage collection happen here, objects from wm1 may no longer exists
Console.log(wm1.get(o2)) // what will happen here? just undefined? null?
}
how GC will affect WeakMaps?
Update: my bad, I missed the fact that you can't have string as keys in WeakMap, my question does not make if I take into account that fact.
WeakMaps are explicitly designed to not exhibit the least observable garbage collection behaviour. There will be absolutely zero issues.
In your specific situtation, as long as you hold a reference to the object or to the function (through the live variables o1 and o2 that are still on the stack), you will be able to find them in the WeakMap or WeakSet. As soon as you don't hold a reference to them any more, and nobody does, they are eligible for garbage collection (just as usual) - and given that, nobody will be able to try to look them up in the collection.
In Kyle Simpson's new title, You don't know JS: ES6 and beyond, I find the following snippet:
WARNING Assigning an object or array as a constant means that value will not be able to be garbage collected until that constant’s lexical scope goes away, as the reference to the value can never be unset. That may be desirable, but be careful if it’s not your intent!
(Excerpt From: Simpson, Kyle. “You Don’t Know JS: ES6 & Beyond.” O'Reilly Media, Inc., 2015-06-02. iBooks.
This material may be protected by copyright.)
As far as I can see, he doesn't expand on this, and 10 minutes on Google turns up nothing. Is this true, and if so, what does "the reference to the value can never be unset" mean exactly? I have got into the habit of declaring variables that won't be changed as const, is this a bad habit in real concrete performance/memory terms?
WARNING Assigning an object or array as a constant means that value
will not be able to be garbage collected until that constant’s lexical
scope goes away, as the reference to the value can never be unset.
That may be desirable, but be careful if it’s not your intent!
That note sounds a bit more of a warning than is necessary (perhaps even a bit silly) and tries to make some sort of special case out of this situation.
With a const variable declaration, you can't assign to the variable something little like "" or null to clear its contents. That's really the only difference in regard to memory management. Automatic garbage collection is not affected at all by whether it is declared const or not.
So, if you would like to be able to change the contents of the variable in the future for any reason (including to manually remove a reference to something to allow something to be garbage collected sooner), then don't use const. This is the same as any other reason for using or not using const. If you want to be able to change what the variable contains at any time in the future (for any reason), then don't use const. This should be completely obvious to anyone who understand what const is for.
Calling out garbage collection as a special case for when not to use const just seems silly to me. If you want to be able to clear the contents of a variable, then that means you want to modify the variable so duh, don't use const. Yes, manually enabling garbage collection on a large data structure that might be caught in a lasting scope/closure is one reason that you might want to change the variable in the future. But, it's just one of millions of reasons. So, I repeat one more time. If you ever want to change the contents of the variable for any reason in the future, then don't declare it as const.
The garbage collector itself doesn't treat a const variable or the contents it points to any different than a var or let variable. When it goes out of scope and is no longer reachable, its contents will be eligible for garbage collection.
const has a number of advantages. It allows the developer to state some intent that the contents this variable points to are not to be changed by code and may allow the runtime to make some optimizations because it knows the contents of the variable cannot be changed. And, it prevents rogue or accidental code from ever changing the contents of that variable. These are all good things when used in an appropriate case. In general, you SHOULD use const as much as practical.
I should add the even some const data can still be reduced in size and make the majority of its contents available for garbage collection. For example, if you had a really large 100,000 element array of objects (that you perhaps received from some external http call) in a const array:
const bigData = [really large number of objects from some API call];
You can still massively reduce the size of that data by simply clearing the array which potentially makes the large number of objects that was in the array eligible for garbage collection if nothing else had a reference to them:
bigData.length = 0;
Remember, that const prevents assignment to that variable name, but does not prevent mutating the contents that the variable points to.
You could do the same thing with other built-in collection types such as map.clear() or set.clear() or even any custom object/class that has methods for reducing its memory usage.
That note in my book was referring to cases like this, where you'd like to be able to manually make a value GC'able earlier than the end of life of its parent scope:
var cool = (function(){
var someCoolNumbers = [2,4,6,8,....1E7]; // a big array
function printCoolNumber(idx) {
console.log( someCoolNumbers[idx] );
}
function allDone() {
someCoolNumbers = null;
}
return {
printCoolNumber: printCoolNumber,
allDone: allDone
};
})();
cool.printCoolNumber( 10 ); // 22
cool.allDone();
The purpose of the allDone() function in this silly example is to point out that there are times when you can decide you are done with a large data structure (array, object), even though the surrounding scope/behavior may live on (via closure) indefinitely in the app. To allow the GC to pick up that array and reclaim its memory, you unset the reference with someCoolNumbers = null.
If you had declared const someCoolNumbers = [...]; then you would be unable to do so, so that memory would remain used until the parent scope (via the closure that the methods on cool have) goes away when cool is unset or itself GCd.
Update
To make absolutely clear, because there's a lot of confusion/argument in some comment threads here, this is my point:
const absolutely, positively, undeniably has an effect on GC -- specifically, the ability of a value to be GCd manually at an earlier time. If the value is referenced via a const declaration, you cannot unset that reference, which means you cannot get the value GCd earlier. The value will only be able to be GCd when the scope is torn down.
If you'd like to be able to manually make a value eligible for GC earlier, while the parent scope is still surviving, you'll have to be able to unset your reference to that value, and you cannot do that if you used a const.
Some seem to have believed that my claim was const prevents any GC ever. That was never my claim. Only that it prevented earlier manual GC.
No, there are no performance implications. This note refers to the practise of helping the garbage collector (which is rarely enough needed) by "unsetting" the variable:
{
let x = makeHeavyObject();
window.onclick = function() {
// this *might* close over `x` even when it doesn't need it
};
x = null; // so we better clear it
}
This is obviously not possibly to do if you had declared x as a const.
The lifetime of the variable (when it goes out of scope) is not affected by this. But if the garbage collector screws up, a constant will always hold the value it was initialised with, and prevent that from being garbage-collected as well, while a normal variable might no more hold it.
The way garbage collectors (GC) work is when something is referenced by nothing ("cannot be reached"), the GC can safely say that something isn't used anymore and reclaim the memory used by that something.
Being able to replace the value of a variable allows one to remove a reference to the value. However, unlike var, const cannot be reassigned a value. Thus, one can't remove that constant from referencing the value.
A constant, like a variable, can be reclaimed when the constant goes "out of scope", like when a function exits, and nothing inside it forms a closure.
var a = {
b: "this";
};
a = null;
When removing the reference to the object literal that 'a' is referencing to in the beginning, will the reference to "this" be removed as well, or will this cause a memory leak?
Do I have to change to code to this:
delete a.b;
a = null;
?
This will not cause a memory leak. A garbage collector typically works by walking the set of live references, marking the set of objects it finds and collecting anything it didn't see. In this case neither the value initially assigned to a or the literal "this" will be found and both will be eligible for collection
Should I free the allocated memory by myself, or is there a kind of garbage collector?
Is it okay to use the following code in JavaScript?
function fillArray()
{
var c = new Array;
c.push(3);
c.push(2);
return c;
}
var arr = fillArray();
var d = arr.pop()
thanks
Quoted from the Apple JavaScript Coding Guidelines:
Use delete statements. Whenever you
create an object using a new
statement, pair it with a delete
statement. This ensures that all of
the memory associated with the object,
including its property name, is
available for garbage collection. The
delete statement is discussed more in
“Freeing Objects.”
This would suggest that you use a delete command to then allow the garbage collector to free the memory allocated for your Array when you're finished using it. The point that the delete statement only removes a reference is worth noting in that it differs from the behaviour in C/C++, where there is no garbage collection and delete immediately frees up the memory.
Memory management in JavaScript is automatic and there is a garbage collector (GC).
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management
You cannot explicitly delete the variables d and arr, but you can remove references to their value by setting the variables to something else, such as null, to allow the GC to remove them from memory.
arr = null;
d = null;
Note that the delete keyword only deletes object properties.
The variables arr and d will exist as global variables and will exist until they are collected by the Garbage Collector.
The variables will be set as properties on the global object i.e. window in a browser environment but since they are declared with var, they will not be deletable from the global object.
In your particular case, the best course of action might be to assign null to the variables after you are finished with them. You may also want to consider containing their scope to a function and do what you need to do with them inside that function.