0

https://tc39.es/ecma262/multipage/ecmascript-language-statements-and-declarations.html#sec-block-runtime-semantics-evaluation

14.2.2 Runtime Semantics: Evaluation

Block : { }

  1. Return empty.

Block : { StatementList }

  1. Let oldEnv be the running execution context's LexicalEnvironment.
  2. Let blockEnv be NewDeclarativeEnvironment(oldEnv).
  3. Perform BlockDeclarationInstantiation(StatementList, blockEnv).
  4. Set the running execution context's LexicalEnvironment to blockEnv.
  5. Let blockValue be Completion(Evaluation of StatementList).
  6. Set the running execution context's LexicalEnvironment to oldEnv.
  7. 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.

Ivar
  • 6,138
  • 12
  • 49
  • 61
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block – epascarello Jan 26 '23 at 14:15
  • hi @epascarello, so that documentation refers to when JS starts executing literally any code between braces (block), right? –  Jan 26 '23 at 14:21
  • hi @T.J. Crowder, Is the statement in my question correct? –  Jan 26 '23 at 14:22

1 Answers1

2

That part of the specification describes how blocks are evaluated.

Does this part of the documentation refer to when JavaScript "puts the focus" on a new execution context...

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, class1, or — in a complicated way — function1,2), since lexical declarations are block-scoped in JavaScript (although again, for function declarations, it's complicated). But blocks don't create a new execution context.

The question is because I am learning closures.

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, not class/function expressions. Since class/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 a class/function declaration is when the class/function keyword appears where a statement is expected by the parser; if it appears where an expression is expected, it's a class/function expression. Examples:

   function ex1() { }
// ^^^^^^^^^^^^^^^^^^−−−−−−−−−−−−−−−−−−−−−−−− function declaration

   export default function() { }
//                ^^^^^^^^^^^^^^−−−−−−−−−−−−− function declaration (yes, really; this is the only place where a name isn't required on a function declaration)

   const ex2 = function() { };
//             ^^^^^^^^^^^^^^−−−−−−−−−−−−−−−− function expression

   const ex2 = function name() { };
//             ^^^^^^^^^^^^^^^^^^^−−−−−−−−−−− function expression

   someArray.forEach((e) => console.log(e));
//                   ^^^^^^^^^^^^^^^^^^^^^−−− function expression

   class Ex4 { }
// ^^^^^^^^^^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−−−− class declaration

   export default class { }
//                ^^^^^^^^^−−−−−−−−−−−−−−−−−− class declaration (yes, really)

   const Ex5 = class { };
//             ^^^^^^^^^−−−−−−−−−−−−−−−−−−−−− class expression

   const Ex6 = class Name { };
//             ^^^^^^^^^^^^^^−−−−−−−−−−−−−−−− class expression

   const Ex7 = register(class { });
//                      ^^^^^^^^^−−−−−−−−−−−− class expression

2 Re the complicated relationship function declarations have with blocks: Originally, function declarations created var-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.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Excellent @T.J. Crowder, so only let, const and class are block-scoped? function I understand, is something else "special" as you say +1 –  Jan 26 '23 at 14:40
  • 1
    @GeorgeMeijer - Other than `function` declarations (which are complicated), yes, only `let`, `const`, and `class` declarations are block-scoped; `var` declarations in functions have function scope whether they're in a block or not, and `var` declarations at global scope create globals (whether they're in a block or not). – T.J. Crowder Jan 26 '23 at 14:59
  • Excellent. `in general, just avoid function declarations in blocks` @T.J. Crowder Do you mean creating functions within an `if(true){ }` block, for example? –  Jan 26 '23 at 15:39
  • the block that the specification talks about is that of an if, for, etc (without considering the function block), right? @T.J. Crowder –  Jan 26 '23 at 16:00
  • 1
    @GeorgeMeijer - Right, it is (blocks can be freestanding, or they can be attached to a flow control structure like an `if`, `while`, etc.). – T.J. Crowder Jan 26 '23 at 16:25
  • Great @T.J. Crowder, one last question. Because a function IS NOT A CONSIDERED A BLOCK, a function does create a new execution context, right? –  Jan 26 '23 at 17:10
  • @GeorgeMeijer - *Calling* a function creates a new execution context for the call, yes: https://tc39.es/ecma262/multipage/ordinary-and-exotic-objects-behaviours.html#sec-ecmascript-function-objects-call-thisargument-argumentslist – T.J. Crowder Jan 26 '23 at 17:15
  • 1
    Great, thank you very much @T.J. Crowder. I always thought a function WAS CONSIDERED BLOCK. Marked as a USEFUL answer –  Jan 26 '23 at 17:21
  • Genius @T.J. Crowder +1, does a function expression also give problems inside a block, or only function declarations? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function –  Jan 26 '23 at 17:38
  • 2
    @Daniel - Function expressions in blocks don't have the complications function declarations do, because they don't create a binding (loosely, a variable) in the scope where they appear. Just function declarations. :-) – T.J. Crowder Jan 27 '23 at 07:10