Variable Scope in JavaScript

Variable Scope in JavaScript

A scope is an area/limit where your variables stay and can only be accessed by other parts of the code in the same area/limit.

Sounds confusing? Let's take a simple example to understand this:

let age = 50; // global scope

function restoreMyYouth() {
  let age = 20; // local scope of this function
  console.log(age); // 20
}

restoreMyYouth();

console.log(age); // 50 - still the same

Let's dive in, to understand the above example in detail.

We have two types of scope available in JavaScript:

  1. Global scope
  2. Local scope

Global scope

If your variable is declared outside a function or any curly braces {} then we consider that it's declared in a global scope. All the functions and curly braces statements inside this scope can access this global variable now.

const name = 'Pankaj';

function myName() {
  console.log(name);
}

console.log(name) // 'Pankaj'

myName(); // 'Pankaj'

In the above example, you can see that name is a global variable that can be accessed inside myName() function. So myName() function will print the name variable, even though the name variable was not declared inside the function.

Local Scope

Variables that are usable in a specific area/boundary of your code are considered to be in a local scope. These local variables can have two kinds of local scope:

  1. Function scope
  2. Block scope

Function scope

Every function has it's own scope. Variables inside a function can only be accessed inside the function. If anything outside that function tries to access that variable then it would not work.

function revealSecret() {
  const trueIdentity = 'Bruce Wayne';

  console.log(trueIdentity); // You can access it inside
}

revealSecret(); // 'Bruce Wayne'

// You can't access this outside the function directly
console.log(trueIdentity); // ReferenceError: trueIdentity is not defined

In the above code, you can see that the variable trueIdentity stays in the scope of revealSecret() function so the trueIdentity variable cannot be accessed outside.

Function scope has another type of scope inside which is called Lexical Scope

What's a Lexical Scope?

If a function is defined in another function then the inner function has access to the outer function's variable, which is called lexical scoping. However, the outer function cannot access the inner function's variables.

Let's understand this with an example:

function earth() {
  const hero = `Batman`;

  function prison() {
    const villain = `Joker`;

    console.log(hero); // 'Batman'
  }

  console.log(villain); // ReferenceError: villain is not defined
}

As you can see in the above example, we have prison() function inside another function named earth(). Our outer function variable hero can get inside prison() function to beat the villain, but the villain variable in prison() function cannot come out.

Block scope

Only let and const are block-scoped. var is only function-scoped and not block-scoped at all.

A block is basically a portion of your code that is surrounded by curly braces {}. If a variable is declared inside these curly braces then it can only be accessed within those curly braces.

{
  const name = 'Pankaj';
  console.log(name); // 'Pankaj'
}

console.log(name); // undefined

Not just the empty curly brace but also other curly braces that we use for if, for etc (except functions) would have the same behavior.

Remember, that this works differently for var. If you declare your variables with var instead of const and let then you wouldn't have any local scope in curly braces at all. So creating a var inside the curly braces will create a global variable like the below example:

if (true) {
  var age = 80;
}

// Prints the variable value as var doesn't respect the block scope rules
console.log(age); // 80

Let's write the above example with let and see the output:

if (true) {
  let age = 80;
}

// Prints undefined because let respects the block scope rules
console.log(age); // undefined

Let's take the below two examples to understand the difference between var and let scope:

// Using var
function myAge() {
  var age = 80;

  if (true) {
    var age = 50; // This will override the age 80
    console.log(age); // 50
  }

  console.log(age); // logs 50
}

// Using let (same behavior for const)
function myAge() {
  let age = 80;

  if (true) {
    let age = 50; // declaring it with let wouldn't change the age declared outside the scope
    console.log(age); // logs 50 inside the scope
  }

  console.log(age); // logs 80
}

This is a very important part of the JavaScript Interviews. A lot of questions are circled around the variable scope.

Let's take one more simple example to understand the scope:

const profile = function() {
  // this is a block and will have its own scope
  {
    let name = 'Edward';
    var age = '17';
  }

  console.log(name); // ""
  console.log(age); // 17
}

profile();

As you can see in the above example that, let is block-scoped so you can't access it outside that block but var is only function-scoped so it can be accessed outside.

Thanks for reading!

Take this cheese 🧀 for making it to the end.