Reputation: 915
I am new to JS and confused with how variables are put into stack and heap. For example,
let num = 5;
let obj = {};
function showNum() {
let num2 = 8;
let obj2 = {}
console.log(num2);
}
showNum();
As you can see from the above code, I created both global and local variables and would like to ask some questions on how variables are put into stack and heap.
Firstly, as you can see there are global variables num
and obj
. The question is:
Are they attached to stack(num) and heap(obj) of global execution context since they are not local variables?
Secondly, there are local variables inside showNum()
function. The question is:
When the function is executed and is pushed into call stack, will num2
and obj2
(I mean reference of obj2
is put into callstack) variables are put into callstack as well? Since I think stack = callstack.
Lastly, is it true that after showNum()
is popped of the callstack, num2
variable is also removed from the stack except for obj2
which is removed by garbage collector?
Upvotes: 0
Views: 70
Reputation: 1074425
Conceptually (e.g., in terms of the specification), global variables are held as bindings in the global environment record. A binding is a combination of a name, current value, and a couple of flags related to the binding (whether it's mutable and whether it's initialized).
Practically, of course, the JavaScript engine can store them in any way it likes provide it behaves according to the semantics of the specification.
The details will be down to the specifics of the JavaScript engine, but it seems likely that global bindings would be held in the heap.
Conceptually, locals are also held in an environment record, one that's created for the call to the function the locals relate to and which may or may not be reclaimed when the function call terminates. I go into some detail on that in my answer here, but briefly, if any function created within the function being called continues to exist after the function returns, conceptually it has a reference to the environment record (more accurately to the lexical environment object the record relates to), which is why functions that close over locals can continue to access those locals after the function containing them returns.
Practically, again, the JavaScript engine can do this any way it likes provided that it conforms to the semantics in the specification, and modern engines are highly optimized. They'll put locals on the stack when possible (including objects). In cases where the locals are referenced by closures created during the function call that survive the termination of the function, the engine will either put them in some kind of environment record object in the first place or move them there from the stack.
Your specific questions:
Are (the globals) attached to stack(num) and heap(obj) of global execution context since they are not local variables?
They're bindings in the environment record for the lexical environment of the global execution context. How that relates to stack vs. heap is an implementation detail.
When the function is executed and is pushed into call stack, will
num2
andobj2
(I mean reference ofobj2
is put into callstack) variables are put into callstack as well? Since I think stack = callstack.
Again, this is an implementation detail as discussed above. Note that it's common for the same stack to be used for both locals and return addresses (and other call metadata), but that doesn't have to be the case. It's up to the implementation.
Lastly, is it true that after showNum() is popped of the callstack,
num2
variable is also removed from the stack except forobj2
which is removed by garbage collector?
Conceptually: Since showNum
doesn't create any functions that continue to exist when it returns, its lexical environment and associated environment record are both released when it returns.
Practically, again, it's down to the implementation. In an optimized engine, it's possible that num2
, obj2
(which contains the reference to the object), and the object are all stored on the stack (the object is quite small, after all), and so popping the stack reclaims all their memory immediately. Or it might be that num2
and obj2
are on the stack but the object obj2
refers to is in the heap, and so popping the stack just removes num2
and obj2
leaving the object with no outstanding references, meaning it's eligible for garbage collection. It's implementation-specific.
Upvotes: 1