A JavaScript function inside a Block Scope: Simplified

Scoping determines the visibility of a variable, an object, or a function.  For example, a variable defined inside a function is visible or can be accessed only inside that particular function.  

JavaScript has 4 types of scope. 

  1. Global scope
  2. Functional scope
  3. Lexical Scope
  4. Block Scope

Out of the above four scoping, Block Scoping became part of JavaScript in ES6.  Any variable declared inside a block with let or const is only accessible inside that block.


function Foo() {

  if (true) {

    let a = 9;
    console.log(a); // 9 
  }

  // a is not defined error 
  // console.log(a); // a is not defined error 
}

Foo();

So, as you see, that variable a is only visible inside the if block and JavaScript throws an error if you try to access it outside the if block.

In the block-level scoping, one important concept is Temporal Dead Zone.  If you try to access a block-level scoped variable before it is declared, JavaScript throws an error, and that area before the declaration is known as Temporal Dead Zone.  It would help if you never try to access a block-level scoped variable before you create it.  

Now let us see how a JavaScript function created inside a block behaves. These two types of function,

  • Function expression
  • Arrow function

behaves in the same way as a block level scoped variable.


function Foo(){

  if(true){
        
        // not defined error 
        // a();
        // b();
    let a = function(){
      console.log(9);
    }

    let b = ()=> console.log(99);   
    a();
    b();
  }
}

You can call function expression and an arrow function after it is declared, and JavaScript throws your error if you try to call them before it is declared.  This behavior is almost the same, if you declare it in other types of scopes.

A function expression and an arrow function declared inside a block using the let statement have the same visibility like a variable. You can not access it before it is declared and also it can not be used outside the block.

The main surprise is the behavior of a function statement or declaration inside a block-level scope. The function statement always gets hoisted on the top of the execution context.  But in the case of block-level scoping, it would be hoisted at the function in which block is created.


function Foo(){

  if(true){
        function a(){
          console.log(9);
        }
        a();
  }

   // console.log(a);
  a();
}

Foo();

You have declared function a inside the if block, so you may expect that its visibility should not be outside the if block. However, that is not that case, and function a is visible in the whole function Foo.

For the above code, you get 9 printed twice, and if you try to access function a before it is declared, JavaScript throws you error a is not a function.

A function statement declared inside a block is visible in the whole function in which block is declared.

Once again look at the below code,


function Foo() {

  console.log(a); // undefined
  if (false) {
    function a() {
      console.log(9);
    }
    a();
  }

  console.log(a); // undefined
  a(); // error - a is not a function
}

Foo();

Can you guess the output? 

We are declaring function a inside the if block, and due to the false condition, JavaScript won’t execute the if block hence won’t create the function a. So, you get undefined printed and an error while calling the function a.

This is all about functions inside a block-level scoping. I hope you find this post useful. Thanks for reading.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s