If I write this in global scope:
(function(){})();
is the anonymous function created when the statement is executed and destroyed immediately after the statement is executed?
As t.niese said, odds are the engine will optimize that function away entirely. So let's assume it has some code in it:
// At global scope
(function(){ console.log("Hi there"); })();
The engine can't guarantee that that code won't throw an error (for instance, if you replaced console
with something else), so I'm fairly sure it can't just inline that.
Now the answer is: It depends.
From a language/specification level, all code in a compilation unit (roughly: script) is parsed when the compilation unit is first loaded. Then, that function is created when the code reaches it in step-by-step execution, executed after being created (which involves creating an execution context for the call), and immediately eligible for garbage collection when done (along with the execution context) because nothing has a reference to it. But that's just theory/high-level specification.
From a JavaScript engine perspective:
- The function is parsed before any code runs. The result of that parsing (bytecode or machine code) will be associated with that function expression. This doesn't wait for execution to reach the function, it's done early (in the background on V8 [Google's engine in Chrome and Node.js]).
- Once the function has been executed and nothing else can refer to it:
- The function object and the execution context associated with calling it are both eligible for GC. When and how that happens depends on the JavaScript engine.
- Which leaves the function's underlying code, either bytecode (modern versions of V8 using Ignition, possibly others) or compiled machine code (somehow the function got used so much it got compiled for TurboFan, or older versions of V8 using Full-codegen, others). Whether the JavaScript engine can then throw away that bytecode or machine code will depend on the engine. I doubt engines throw away byte/machine code they've generated for a function if they may need it again (e.g., for a new anonymous function created by a new call to
foo
). If foo
became unreachable, maybe foo
's byte/machine code and the anonymous function's could be tossed as unnecessary. I have no idea whether engines do that. On the one hand, it seems like low-hanging fruit; on the other, it seems like something that would be so uncommon it's not worth bothering with. (Remember, here we're not talking about code attached to a function instance, but the code that has been produced from the source that gets attached to an instance when the instance is created, and may get attached to multiple instances over time.)
Here are a couple of articles on the V8 blog that make interesting reading:
if I write this in a function:
function foo()
{
var a=1;
(function(){})();
a++;
}
Does the anonymous function exist until foo returns, or just exist during the execution of that statement?
Let's assume again there's a console.log
in that function, and that I'm correct (it is an assumption on my part) that the fact it relies on a writable global (console
) means it can't just be inlined.
The high-level/specification answer is the same: The function is parsed when the script is loaded, created when it's reached, executed, and eligible for GC when it's done executing. But again, that's just high-level concept.
Things are probably different at the engine level:
- The code will be parsed before any code in the script runs.
- Bytecode or machine code is likely generated before any code in the script runs, although I seem to recall something from the V8 blog about parsing but not immediately compiling the contents of top-level functions. I can't find that article, though, if it wasn't just in my head.
- When execution reaches the function, a function object for it is created along with an execution context (unless the engine is sure it can optimize that away without it being observable in code).
- Once execution ends, the function object and that execution context are eligible for GC. (They may well have been on the stack, making GC trivial when
foo
returns.)
- The underlying code, though, sticks around in memory in order to be used again (and if used often enough, optimized).