Block vs Function Scope in Javascript

What are the similarities and differences between block scope and function scope?

Block Scope and Function Scope:

Both function scope and block scope are fundamental concepts in JavaScript that control the visibility and lifetimes of variables and parameters.

Similarities:

  1. Both block scope and function scope are used to limit the visibility and life-cycle of variables within JavaScript.

  2. Both scoping rules prevent variables from polluting the global namespace and thus potentially causing naming conflicts or unexpected behavior in the code.

Differences:

  1. Function Scope: In JavaScript, function scope means that variables declared within a function using the var keyword are only accessible within the function they’re declared. This means that if you declare a variable inside a function, you cannot access this variable outside the function.

  2. Block Scope: Block scope, on the other hand, was introduced in ES6 with the let and const keywords. If a variable is declared in a block (i.e., within {} braces), that variable is only accessible within that block and its nested blocks. This could be any code block like an if block, a for or while loop, or even just a standalone block.

In essence, all function scopes are block scopes as the function body is a block. However, not all block scopes are function scopes, as blocks can exist outside of functions (for example, within a loop or conditional statement).

In JavaScript, understanding the difference between function and block scope, and when to use var, let, and const is important for managing variable visibility, preventing unexpected behavior, and writing clean, maintainable code.

Function Scope

Here is a simple example to illustrate function scope:

With function scope, a variable declared inside a function is only accessible within that function. If you try to access it from outside the function, it won’t work.

1
2
3
4
5
6
7
function myFunction() {
  var functionScoped = 'Hello, World!';
  console.log(functionScoped); // 'Hello, World!'
}

myFunction();
console.log(functionScoped); // Error: functionScoped is not defined

Block Scope

In contrast, with block scope, a variable declared inside a block {} (like within an if statement, for loop, or simply within standalone curly braces) using let or const is only accessible within that block and its sub-blocks. If you try to access it from outside the block, it won’t work.

1
2
3
4
5
6
{
  let blockScoped = 'Hello, World!';
  console.log(blockScoped); // 'Hello, World!'
}

console.log(blockScoped); // Error: blockScoped is not defined
1
2
3
4
5
for (let i = 0; i < 5; i++) {
  console.log(i); // 0, 1, 2, 3, 4
}

console.log(i); // Error: i is not defined

Lexical Scope

Lexical scope (also known as static scope) in JavaScript refers to the accessibility or visibility of variables, functions, and objects based on their physical location in the source code during the write-time of the code.

Here’s a simple example of lexical scoping:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
function outerFunction() {
    let outerVar = 'I am outside!';

    function innerFunction() {
        console.log(outerVar); // 'I am outside!'
    }

    innerFunction();
}

outerFunction();

In this example, outerVar is defined in the scope of outerFunction. However, innerFunction, which is defined and called inside outerFunction, has access to outerVar. This is because JavaScript’s lexical scoping rules allow functions to access variables defined in their outer scope.

In other words, the JavaScript engine determines at write-time that outerVar is accessible inside innerFunction due to their physical locations in the code, hence the term “lexical” (relating to text or words) scoping.