JavaScript Basics- Scopes & Hoisting

JavaScript Basics- Scopes & Hoisting

If you're a JS beginner, you must have heard about these words.

Let's get in depth to understand more about these concepts in JS.

What is a Scope in JS?

A scope in JS is a context in which values and expressions are visible or can be referenced. In simple words, Scope is the accessibility of variables, functions, and objects in some particular part of your code during runtime.

Types of scopes in JS:

JavaScript has 3 types of scopes :

  • Global Scope : Any variable, function, expression that is present globally or not declared inside any other function belongs to the global scope. Variables, functions that declared in global scope can accessed from anywhere in the program.
var foo=23; // declared in the global scope

function greet(){
console.log(foo);
} 

greet();// Prints '23'
console.log(foo)l //Prints '23'
  • Local or Function Scope : Variables and functions that are enclosed in some other function become part of that function's local or function Scope. In other words, a local scope or function scope is associated with a function, when we declare variables and functions inside another function, they become part of the local/function scope and are restricted to that scope. Variables and function declared in function/local scope are accessible within that scope.
//Declared in Global Scope
var foo=23;

function bar(){ 
// Function or Local Scope
   var message="Hello JavaScript"; // inside the local/function 
                                   scope of bar 
   console.log(message); // Prints 'Hello JavaScript' 
   console.log(foo); // Prints '23'
}

//Global Scope
console.log(message); // Uncaught ReferenceError: message is not 
                         defined
  • Block Scope : Variables declared with let and const can block scoped. That is, they can be enclosed within a pair of curly braces(blocks). Any variable/function declared with let or const, inside a pair of curly braces are only available within the scope of the braces. It stands true for only for variables that declared with let and const and not with var.
{ //Block scope
  let message = 'Hello JavaScript'; // declared with let
  var name = 'Debarshi'; // declared with var
  console.log(message); // Prints 'Hello JavaScript'
}

//Global scope
console.log(name);// prints 'Debarshi'
console.log(message); // Uncaught ReferenceError: message is not 
                         defined

Hoisting in JS:

In JavaScript, hoisting is a concept in which a function or a variable can be used before declaration.

Hoisting with variables and functions declared with var keyword.

Variables declared with var keyword gets hoisted to the top of the scope. If accessed before initialization they result undefined.

console.log(baz); // Prints 'undefined'

console.log(greet); // Prints 'undefined

greet(); // Prints 'TypeError: greet is not a function'

var baz="Hello World!";

//anonymous function stored in a variable
var greet=function(){
    console.log("Hello JavaScript!");
}

greet(); // Prints 'Hello from JavaScript!'

Hoisting with variables and functions declared/assigned with let and const keyword

Although variables and functions declared/assigned to let and const are also hoisted, but they cannot be accessed until they have been initialized.

console.log(a); // Prints 'ReferenceError: Cannot access 'a' 
                    before initialization'
console.log(name); // Prints 'ReferenceError: Cannot access 'm' 
                       before initialization'

doSomething(); // Prints 'ReferenceError: Cannot access 'm' before 
                   initialization' 

let a = 45; // Initialized
const name="Debarshi"; // Initialized

const doSomething = function (){
   console.log("Hello World!")
}

console.log(a) // Prints '45'

console.log(name) // Prints 'Debarshi'

doSomething(); // Prints 'Hello World!'

Hoisting with functions:


  • Functions declared with function keyword: Functions that are declared with the function keyword are also hoisted and can accessed from the top of the scope.
 ```
   foo(); // Prints 'Hello from foo!'

   function foo(){
      console.log("Hello from foo!");
    } 
 ```


  • Anonymous functions, functions expression:

    As anonymous functions and function expressions are assigned/stored to a variable, they behave same as that of the variable depending on the variable type they are assigned to.

 ```
   baz(); // TypeError: baz is not a function
   foo();  // Uncaught ReferenceError: Cannot access 'foo' 
              before initialization

   var baz=function(){ // assigned to var
   console.log("Hello from Baz");
   }

  let foo=()=>{  assigned to let
   console.log("Hello from Foo");
  }

  baz(); // Prints 'Hello from Baz'
  foo(); // Prints 'Hello from Foo'
 ```

Temporal Dead Zone in JS:

let and const variables cannot be read/written until they have been fully initialized, which happens when they are declared (if no initial value is specified on declaration, the variable is initialized with a value of undefined). Accessing the variable before the initialization results in a ReferenceError.

  { // TDZ starts at beginning of scope
  console.log(bar); // undefined
  console.log(foo); // ReferenceError
  var bar = 1;
  let foo = 2; // End of TDZ (for foo)
 }

Originally posted on : dev.to/debarshi95/javascript-basics-scopes-..

References:

MDN