1

I was playing around with JS scopes to get a better understanding of the concept. Doing that I wrote the following script:

{
  let a;
  function x() {
    let p;
    var q;
  }
}

x();

Surprisingly, when debugging in the Chrome dev console, I realized that if I stop the script at line 2 or let a, I can see the block scope having both variable a and function x as visible in screenshot 1.

Also, on logging window.x outputs undefined However, as soon as I jump on to the next breakpoint which is line 4 or let p, the block scope is no longer there and a local scope is created. Now, on logging window.x outputs the function definition.

Now as I understand, since I am able to call x() from the global scope means that the function declaration is available in the global scope. Then why isn't the function binding available before the creation of function's execution context (if it is hoisted to global scope)? And why does writing x() at the top of the block output TypeError: x is not a function?

screenshot 1

Note: I am not writing functions like this anywhere, i just wrote this script to test my understanding of scopes. Apologies if this is a wrong way of writing functions.

EDIT per comments:

Chrome and FF show undefined while Safari shows function definition.

console.log(x); // logs undefined
{
  let a;
  function x() {
    let p;
    var q;
  }
}

x();
Randy Casburn
  • 13,840
  • 1
  • 16
  • 31
Samarth Saxena
  • 175
  • 3
  • 18
  • 1
    I really recommend reading YDKJS: https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/scope-closures/README.md – Josh Mathews Oct 28 '21 at 16:33
  • this: "_Then why isn't the function binding available before the creation of function's execution context_" - it is - prior to your openning `{`, add `console.log(x);` and it will log the function definition. – Randy Casburn Oct 28 '21 at 16:47
  • @RandyCasburn i tried and it just prints `undefined`. That is pretty much my question as to why before the creation of function execution context, the value of x on window is `undefined`? – Samarth Saxena Oct 28 '21 at 17:16
  • May I edit your question to put this into a stacksnippet? – Randy Casburn Oct 28 '21 at 17:40
  • @RandyCasburn Running the code snippet shows `undefined` instead of the function definition – Samarth Saxena Oct 28 '21 at 18:18
  • Which browser are you using? – Randy Casburn Oct 28 '21 at 18:44
  • Yes, I see in Chrome & FF it returns undefined. In Safari it returns the function definition. – Randy Casburn Oct 28 '21 at 18:47
  • [I can write an answer, but I have no ref to the spec] MDN says, that function definitions are "[...] hoisted to the top of the enclosing function or global scope". For non-function scopes it seems to be browser dependent (MDN only talks about the if scope, but I guess `{ ... }` results in the same scope). For some it appears to be hoisted to the top of the global scope (Safari), for some it seems to be hoisted to the top of the local scope. However, I guess, that in all browsers, at least inside the scope it is hosted to the top (e.g. if you do `console.log(x)` right before or after `let a`). – A_A Oct 28 '21 at 19:50
  • Always use strict mode to not get confused by legacy behaviour :-) – Bergi Oct 28 '21 at 21:42

0 Answers0