Skip to content Skip to sidebar Skip to footer

How Does This Hoisting Work With Block Scope?

I've been asked about a question Why the third output is 1 instead of 2? There should be no block scoped foo being created since there is neither let nor const in that block. But

Solution 1:


According to the web compat semantics at the place of the function declaration, the value of the blocked scope variable is bound to the outer scope². This code is equivalent to:

let outerFoo; // the functions create a binding outside of the scope

{
  let innerFoo; // but also inside// due to hoisting, functions get bound before any code get's executed:
  innerFoo = functionfoo() {
    console.log('A');
  };
  innerFoo =   functionfoo() {
    console.log('B');
  };
  
  // At the place of the function declaration, the variable leaves the scope/* function foo() {
    console.log('A');
  } */
  outerFoo = innerFoo;

  innerFoo();
  
  innerFoo = 1;
  
  // this also applies to the second declaration/* function foo() {
    console.log('B');
  } */
  outerFoo = innerFoo;
  
  innerFoo = 2;

  console.log(innerFoo);
}
console.log(outerFoo);

²This is basically exactly how the specification describes it:

When the FunctionDeclaration f is evaluated, perform the following steps in place of the FunctionDeclaration Evaluation algorithm provided in15.2.6:
a. Let fenv be the running execution context's VariableEnvironment.
b. Let benv be the running execution context's LexicalEnvironment.
c. Let fobj be ! benv.GetBindingValue(F, false).
d. Perform ! fenv.SetMutableBinding(F, fobj, false).

The specification additionally states:

Prior to ECMAScript 2015, the ECMAScript specification did not define the occurrence of a FunctionDeclaration as an element of a Block statement's StatementList. However, support for that form of FunctionDeclaration was an allowable extension and most browser-hosted ECMAScript implementations permitted them. Unfortunately, the semantics of such declarations differ among those implementations. Because of these semantic differences, existing web ECMAScript code that uses Block level function declarations is only portable among browser implementation if the usage only depends upon the semantic intersection of all of the browser implementations for such declarations

So Safari is probably doing it the way it always did it, while Chrome (and Firefox) follow the specification.

Post a Comment for "How Does This Hoisting Work With Block Scope?"