Search code examples
javascriptscopehoisting

How JS hoisting works with block statement?


In this following snipet, I just want to understand why console.log(abc in this); is print true , but in next line console.log(abc); getting undefined

console.log(this.abc);//undefined
console.log(abc in this);//true
console.log(abc);//undefined
{
    function abc(){
        console.log("hello");
    }
}
console.log(abc); //ƒ abc(){console.log("hello");

Could anyone of you explain how Hoisting and Block statement working in this case?


Solution

  • In sloppy mode, this refers to the global object. A function inside a plain non-function block like that will have its variable name hoisted to the outer scope, but the actual function will not be assigned to the outer variable (to the window property) until the inner block is executed.

    See here for details:

    What are the precise semantics of block-level functions in ES6?

    As explained in that other question, to the interpreter, your code looks something like this:

    window.abc = undefined; // top-level hoisting assigns to window properties
    console.log(window.abc); // undefined
    console.log(window.abc in window); // true
    console.log(window.abc); // undefined
    {
      var _abc = function abc() {
        console.log("hello");
      };
      window.abc = _abc;
    }
    console.log(window.abc); //ƒ abc(){console.log("hello");

    The reason abc in this is true is because abc has been initialized as a property of the window object, but it hasn't been assigned a value yet. It's similar to what's happening here:

    const obj = { foo: undefined };
    console.log('foo' in obj);