I have looked all over the internet and I can't seem to find an answer to this question.
I read that the stack is used to store primitives and heap is for objects.
I also read that the stack's size is fixed and once allocated it does not change, hence why it's used for primitives, because JS knows the size of each variable before runtime.
I also know that primitives are immutable, so if we try to reassign a variable, it will not change the value at its memory address but will rather allocate new space in memory, store the new value and assign its address to the variable.
If the above is correct, then what happens when I do this?
let string = "Hello World"; // Memory allocated for "Hello World"
string = string.ToUpperCase(); // New memory allocated for "HELLO WORLD"
Where does the new memory for HELLO WORLD get allocated? Is it in the stack because it's a primitive? Or is it in the heap because JS does not know its value until it runs the code?
If it's in the stack, what happens to the old "Hello World" then? Since only the heap is garbage collected does that mean that the old, unused, string will stay there until the program finishes running?
What happens if I do
string = string.repeat(10000000000)
If the stack can't grow, does it mean that at some point I can stack overflow because a variable is too large?
Thank you.
The answer may vary by engine, and it really doesn't matter to your code. Worry about running out of stack if/when you run out of stack. JavaScript's specification doesn't require implementations to do one thing or the other. It describes behavior, not the implementation of that behavior.
But speaking practically: It seems unlikely that a JavaScript engine would try to put a massive string on the stack. More likely, it would put it in the heap. That doesn't mean it can't put other strings on the stack. Maybe it decides based on size. Maybe it decides based on lifetime — perhaps it'll put a small string used only locally in a function on the stack, but put a massive one, or one retained globally, on the heap.
The point is: Modern JavaScript engines are complicated and highly, highly optimized. They're unlikely to take such a simplistic view as "primitives go on the stack and objects go on the heap."
I read that the stack is used to store primitives and heap is for objects.
Not necessarily. Objects can be allocated on the stack as well, and have been by at least some JavaScript engines at various points in history. If an object won't survive the end of the function call, and isn't massive, putting it on the stack makes reclaiming it when the function returns dead easy.
I also know that primitives are immutable, so if we try to reassign a variable, it will not change the value at its memory address but will rather allocate new space in memory, store the new value and assign its address to the variable.
Without getting too deep into theory, again this could well be implementation-specific. Consider a = 1
. We have no way of telling whether that puts the value 1
in the memory associated with a
, or puts a reference to an immutable singleton representing 1
in a
. The former seems more a lot more likely than the latter (for numbers; strings are another matter), but we don't know and can't know (in the general case; we can for a specific version of a specific engine), because it makes no difference to our code and the spec doesn't require one behavior or the other.