First, a quick disclaimer: There's a difference here between the theory and the optimized process that modern JavaScript engines actually perform.
Let's start with the theory:
The object isn't on the stack, just the variable that contains the reference to the object. The object exists separately, and is created in the heap. So in your example, just before the function returns, we have this in memory:
+−−−−−−−−−−−−−−−−−−+
| (object) |
+−−−−−−−−−−−−−−−−−−+
[obj:Ref11254]−−−−−>| name: "someName" |
+−−−−−−−−−−−−−−−−−−+
obj
, the variable, contains a reference to the object (Ref11254
, though of course that's just a conceptual number, we never actually see these). When your function returns, the content of obj
(Ref11254
) is returned, and obj
(the variable) disappears along with the rest of the stack. But the object, which exists separately, continues to exist as long as something has a reference to it — in your case, the newObj
variable.
In practice:
As an optimization, modern JavaScript engines frequently allocate objects on the stack (subject to engine-specific size constraints). Then, if the object is going to continue to live after the function terminates and the stack is cleaned up, they copy it into the heap. But if the object isn't going to survive (that is, no reference to it has been kept or is being returned), they can let it get cleaned up along with the stack. (Why? Because stack allocations and cleanup are really fast, and a lot of objects are only used locally in functions.)
It's worth noting that the same question arises for variables if the function creates a function:
function getFunction() {
var x = 0;
return function() {
return x++;
};
}
var f = getFunction();
console.log(f()); // 0
console.log(f()); // 1
console.log(f()); // 2
Now it's not just that the function getFunction
returns (which is an object) survives, but so does x
! Even though variables are "on the stack," and the stack gets reclaimed when getFunction
returns. How is that possible?!
The answer is that conceptually, local variables aren't on the stack. Putting them on the stack is an optimization (a common one). Conceptually, local variables (along with a few other things) are stored in an object called a LexicalEnvironment object which is created for the call to getFunction
. And conceptually, the function getFunction
returns has a reference to that LexicalEnvironment object, and so it (and the variables it contains) continues to live on even after getFunction
returns. (The function getFunction
returns is called a closure because it closes over the environment where it was created.)
And sure enough, in practice modern JavaScript engines don't really do that. They create variables on the stack where it's quick and easy to clean them up. But then if a variable is going to need to live on (like x
needs to in our example above), the engine puts it (and any others that it needs to keep around) into a container in the heap and has the closure refer to that container.
More about closures in this question's answers and on my anemic little blog (using slightly outdated terminology).