14.2.2 Runtime Semantics: Evaluation
Block : { }
- Return empty.
Block : { StatementList }
- Let oldEnv be the running execution context's LexicalEnvironment.
- Let blockEnv be NewDeclarativeEnvironment(oldEnv).
- Perform BlockDeclarationInstantiation(StatementList, blockEnv).
- Set the running execution context's LexicalEnvironment to blockEnv.
- Let blockValue be Completion(Evaluation of StatementList).
- Set the running execution context's LexicalEnvironment to oldEnv.
- Return ? blockValue.
Does this part of the documentation refer to when JavaScript "puts the focus" on a new execution context (e.g. when you start executing a function)?
The question is because I am learning closures.
That part of the specification describes how blocks are evaluated.
Not quite. A block with statements in it creates a new declarative lexical environment (Step 2), not a new execution context; it does then set this new environment record as the running execution context's LexicalEnvironment (Step 4). The declarative lexical environment for the block is there to contain any lexical declarations inside the block (that is, declarations using
let
,const
,class
1, or — in a complicated way —function
1,2), since lexical declarations are block-scoped in JavaScript (although again, forfunction
declarations, it's complicated). But blocks don't create a new execution context.There's a bit of a relationship between this and closures, in that a closure closes over the current environment record where it's created. So if you're wondering if a closure created within the block closes over the bindings within the block: Yes, it does.
1 Note we're talking about
class
/function
declarations here, notclass
/function
expressions. Sinceclass
/function
expressions don't create a binding (loosely, a variable) in the scope where they appear, they aren't relevant to this discussion. (Recall that aclass
/function
declaration is when theclass
/function
keyword appears where a statement is expected by the parser; if it appears where an expression is expected, it's aclass
/function
expression. Examples:2 Re the complicated relationship
function
declarations have with blocks: Originally,function
declarations createdvar
-style function-scoped globals, and declaring functions in blocks didn't have specified behavior (it was an allowed extension to the spec, and they were done differently by different JavaScript engines [or even the same engine between versions]). Recent versions of the specification have codified the ways in which major implementations overlapped with regard to function declarations in blocks, which includes some block-level semantics. I go into the gory details in Chapter 3 of JavaScript: The New Toys, but really, in general, just avoid function declarations in blocks (use an expression instead); not all situations have specified behavior, and the behavior that is specified may be surprising.