JavaScript: Variable Scope [ includes scope chain and const scope ]

Understanding the scope of a variable is really a critical part of learning JavaScript. By using the variable in a place where it is not available will throw errors and/or introduce bugs.

DEFINITION

Scope of the variable defines-

In which part of the code the variable will be available.

If you want to know about variable and constant declaration in detail, check the details of declaration and initialization-

The variable scope in JavaScript has changed a lot over time. In this article, we have discussed different scopes of variables in JavaScript. We have also the discusses scope of a constant and compared all the scopes in detail.

Scope in a Nutshell

Here is a brief of the scope of a variable declared with “var” or “let“, and a constant declared with “const“-

varletconst
Global
Function
BlockBlock

NOTES

  • A global scope means, places in the code which are not wrapped in any block.
  • Function scope means, in the function definition wrapped in-
    function someFuncNameHere() {
    // variable defined here
    }
  • Block scope means any place that is defined by wrapping in curly braces “{“(start) and “}“(end). Can be a loop, condition block, function block, etc.
    {
    // variable defined here
    }

In the later parts of the article, we will discuss all the cases of these scopes and scope chain, in detail-

Global scope with “var

Define a variable with “var“, and place it in the global scope, directly in the file (not in any function or other block). That variable will be accessible from anywhere.

Not only it will be accessible from anywhere, but it will also be available on the global object. In the case of a browser, the global variable is “window“, so the global variable will be available in the “window” object.

Case #1: Define a global variable

  • Here we are defining a variable “bigBox” with a “var” keyword.
  • Then we can access it using the variable name “bigBox” and also by using “window.bigBox”.
  • This variable stays in the global scope and can be accessed from anywhere.
// Define a variable with "var" in the global scope
var bigBox = true;

console.log(bigBox);
console.log(window.bigBox);

Output:

true
true

Case #2: window property as a variable

  • If we define a property in the “window” object, we can access it directly by using the property name only. Like, where we have added a property named “myCustom”
  • This “window.myCustom” can be accessed from anywhere in the code, by both “window.myCustom” and “myCustom”.
// Define a value in window object
window.myCustom = 99;

console.log(myCustom);
console.log(window.myCustom);

Output:

99
99

Case #3: Variable defined in a Loop

  • Here we have 2 variables in a loop. One is “i”, which is used to count the loop steps. And another one is “testVarInsideLoop”, this one is defined inside the loop. 
  • Both these variables are defined using “var”.
  • These variables are accessible inside the loop.
  • Also, outside the loop, we can access these variables. The value outside the loop will have the value that was last set inside the loop.
for (var i = 0; i < 5; i++) {
    var testVarInsideLoop = i * 10;

    console.log("i inside the loop: " + i);
    console.log("testVarInsideLoop inside the loop: " + testVarInsideLoop);
}

console.log("i outside the loop: " + i);
console.log("testVarInsideLoop outside the loop: " + testVarInsideLoop);

Output:

i inside the loop: 0
testVarInsideLoop inside the loop: 0

i inside the loop: 1
testVarInsideLoop inside the loop: 10

i inside the loop: 2
testVarInsideLoop inside the loop: 20

i inside the loop: 3
testVarInsideLoop inside the loop: 30

i inside the loop: 4
testVarInsideLoop inside the loop: 40



i outside the loop: 5
testVarInsideLoop outside the loop: 40

Function scope with “var

  • Define a variable inside a function using “var”. Here we have defined a variable “myTestVarInFunc”, inside the function “bigBoxFunc”.
  • This variable can be accessed anywhere inside the function using the variable name.
  • This variable will not be added to the global scope (inside the “window” object in browser).
  • This function-scoped variable can not be accessed outside the function.
function bigBoxFunc() {
    var myTestVarInFunc = 100;

    console.log("myTestVarInFunc inside function: " + myTestVarInFunc);
    console.log("window.myTestVarInFunc inside function: " + window.myTestVarInFunc);
}

bigBoxFunc();

console.log("myTestVarInFunc outside function: " + myTestVarInFunc);

If we try to access the function scoped variable “myTestVarInFunc”, outside the function, It will throw an error-
Uncaught ReferenceError: myTestVarInFunc is not defined

Output:

myTestVarInFunc inside function: 100
window.myTestVarInFunc inside function: undefined

Uncaught ReferenceError: myTestVarInFunc is not defined

Block scope with “let

Let’s see what happens if we define a variable using “let”.

Case #1: Variable defined in the script

This is not actually a block scope example, but this is to demonstrate the basic behavior of a variable declared with “let”, in the script outside any block.

  • We have variables here named “foo” and “bar”, defined using “let”. This is not inside any block, but in the script.
  • We can access the variables from inside a function or any block of code.
  • We can change the variable inside a function or in any other block.
let foo = 99;
let bar = 100;

function someOperation() {
    // Change bar
    bar = 789;

    console.log("foo inside function: " + foo);
    console.log("bar inside function: " + bar);
}

// Call the function
someOperation();

// Check variables in the main script
console.log("foo outside any block: " + foo);
console.log("bar outside any block: " + bar);

// Check if these varialbes are added to the global window object
console.log("window.foo: " + window.foo);

The variable defined with “let” is not added to the global object (window in the case of the browser).

Output:

foo inside function: 99
bar inside function: 789

foo outside any block: 99
bar outside any block: 789

window.foo: undefined

Case #2: Variable defined in a block

  • Variable defined in a block using “let” can only be accessed inside the block.
  • Any block(including a function or a loop) will have this behavior, of a variable defined with “let”.
{
    let bigBoxBlock = 1007;

    console.log("bigBoxBlock inside the block: " + bigBoxBlock);
        
}

console.log("bigBoxBlock outside the block: " + bigBoxBlock);

Output:

bigBoxBlock inside the block: 1007

Uncaught ReferenceError: bigBoxBlock is not defined

Case #3: Variable defined in a loop

  • Variable defined with “let” for the iterator to run a loop can be accessed in the loop block, and also outside the loop.
  • Variable defined with “let” inside a loop block, can only be accessed inside the loop block. We can not access that variable outside the loop block.
for (let i = 0; i < 5; i++) {
    let testVarInsideLoop = i * 10;

    console.log("i inside the loop: " + i);
    console.log("testVarInsideLoop inside the loop: " + testVarInsideLoop);
}

console.log("i outside the loop: " + i);
console.log("testVarInsideLoop outside the loop: " + testVarInsideLoop);

Output:

i inside the loop: 0
testVarInsideLoop inside the loop: 0

i inside the loop: 1
testVarInsideLoop inside the loop: 10

i inside the loop: 2
testVarInsideLoop inside the loop: 20

i inside the loop: 3
testVarInsideLoop inside the loop: 30

i inside the loop: 4
testVarInsideLoop inside the loop: 40

Uncaught ReferenceError: i is not defined

Block scope with “const

Constants defined using “const” have a block scope. So the scope is similar to the variables defined with “let”.

  • Constants defined outside any block can be accessed from anywhere.
  • Constants defined in the main script, outside any block are not added to the global scope(window in the case of the browser).
  • Constant defined in a block(like a function or a loop or any other block) can not be accessed from anywhere else.
const foo = 99;

function someOperation() {
    console.log("foo inside function: " + foo);
}

// Call the function
someOperation();

// Check constant in the main script
console.log("foo outside any block: " + foo);

// Check if these constants are added to the global window object
console.log("window.foo: " + window.foo);


// Define a block
{
    const bigBoxBlock = 1007;

    console.log("bigBoxBlock inside the block: " + bigBoxBlock);
        
}

// Check constant defined in a block
console.log("bigBoxBlock outside the block: " + bigBoxBlock);

Output:

foo inside function: 99
foo outside any block: 99
window.foo: undefined

bigBoxBlock inside the block: 1007
Uncaught ReferenceError: bigBoxBlock is not defined

Scope chain

The scope chain is Lexicaly defined. So we have to check where the function/variable is defined.

If some variable or function is used somewhere, then JavaScript looks for the definition in the same scope first. If it’s not found in the same scope, then it looks in the immediate outer scope. and then the outer scope of that, if required.

JS variable lexical scope chain
JS variable lexical scope chain

All these scope chain related information is true for variables defined with “var“, or “let” and also for constants defined with “const“.

Let’s check all possible cases of accessing a variable using lexical scope chaining-

Case #1: Variable defined in another function

Variable defined in a function can not be accessed from another function.

function firstFunc() {
    console.log("Inside firstFunc");

    // Try to access variable declared in firstFunc
    console.log(mySecondVal);
}

function secondFunc() {
    console.log("Inside secondFunc");

    // Define variable
    var mySecondVal = 107;

    // Call firstFunc
    firstFunc();
}


secondFunc();

Output:

Inside secondFunc

Inside firstFunc
Uncaught ReferenceError: mySecondVal is not defined

Case #2: Variable defined in outer function

If we have a function defined inside another function, then the variables defined in the outer function can be accessed from the function(s) defined inside it.

function secondFunc() {
    console.log("Inside secondFunc");

    // Define variable
    var mySecondVal = 107;

    function firstFunc() {
        console.log("Inside firstFunc");
    
        // Try to access variable declared in firstFunc
        console.log(mySecondVal);
    }

    firstFunc();
}


secondFunc();

Output:

Inside secondFunc

Inside firstFunc
107

Case #3: Variable defined in both inside and outer function

If a variable is defined in the global scope and we try to access it in an inner function, then we can access it.

The variable just needs to be somewhere in the outer scope.

// Define variable
var mySecondVal = 107;

function secondFunc() {
    console.log("Inside secondFunc");

    function firstFunc() {
        console.log("Inside firstFunc");
   
        console.log(mySecondVal);
    }

    firstFunc();
}


secondFunc();

Output:

Inside secondFunc

Inside firstFunc
107

Case #4: Variable defined in all outer scope

If the variable is defined in multiple places of the lexical scope, then the variable that is in the closest scope will be used.

// Define variable
var mySecondVal = 11;

function foo() {
    console.log("Inside foo");

    // Define mySecondVal again
    var mySecondVal = 22;
    
    function bar() {
        console.log("Inside bar");

        // Define mySecondVal third time
        var mySecondVal = 33;

        function barInsider() {
            console.log("In the barInsider function");
            
            console.log(mySecondVal);
        }

        barInsider();
    }

    bar();
}


foo();

Output:

Inside foo

Inside bar

In the barInsider function

33

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.