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?
Some high-level languages, such as JavaScript, utilize a form of automatic memory management known as garbage collection (GC). The purpose of a garbage collector is to monitor memory allocation and determine when a block of allocated memory is no longer needed and reclaim it.
You can't force garbage collection (not in any sane fashion). If your variables aren't going out of scope automatically, just set them to null . Show activity on this post. Best advice is to define them in scope that makes them eligible for garbage collection.
Garbage collection is performed automatically. We cannot force or prevent it. Objects are retained in memory while they are reachable.
gc() asks the garbage collector to run, but the garbage collector never makes any guarantees about when it will run or what unreachable objects it will free from memory. Option C is wrong. The garbage collector runs immediately the system is out of memory before an OutOfMemoryException is thrown by the JVM.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With