JavaScript: The Birth Of Block Scope
In JavaScript, Traditionally there were Global and Local scopes. Any variable that is declared inside a function has Local Scope. Any variable that is declared outside any functions has Global Scope.
Before getting on to the block scope, let's discuss how the scope chain works.
Scope Chain
In the below example, the sibling functions func2 and helper have access to the variables declared in their common parent function func1 and the Global context.
The scope chain always flows downwards.
Let's see how the JavaScript engine looks for a variable when required.
Task #1: Access variable a from within the context func2
Is variable a exist in func2? — No.
Does func2 have any parent lexical environment? — Yes. func1!
Is variable a exist in func1? — No.
Does func1 have any parent lexical environment? — Yes. The Global context.
Is variable a exist in the Global context? — Yes! Returning a.
Task #2: Access variable d from within the context func2
Is variable d exist in func2? — No.
Does func2 have any parent lexical environment? — Yes. func1!
Is variable d exist in func1? — No.
Does func1 have any parent lexical environment? — Yes. The Global context.
Is variable d exist in the Global context? — No.
Does the Global execution context have any parent lexical environment? — No! It is a Reference Error!
In JavaScript, a variable can be accessed if it exists in the current lexical environment or in the preceding lexical-environment-chain which extends on to the global context. Every search ends in the Global context.
Shortcomings With The Broader Scopes
In the above example, the variable a has a Global Scope. It is never advised as it allows any function to access or even modify the value.
The function scope can also get really bloated. Nothing stops a programmer from writing a function with thousands of lines. In the below example, the incrementors i and j are visible throughout the function func1 which technically may not end.
The usage of var also makes the variables accessible even before their declaration. That is hoisting and that is for another discussion.
Block Scope
With the introduction of let and const in the ES2015, the scope of the variables is reduced to the block they exist in. A block is anything wrapped around a pair of curly braces {}, mostly a loop or a conditional statement.
The reduced scope leads to reduced noise and pollution. var is going to be there in JavaScript maybe forever to allow the legacy systems to run. So, it is good to embrace let and const to create a pollution-free JavaScript environment.