Scope in JavaScript: Global vs. Local vs. Block
Scope
Scope in JavaScript defines where a declared variable or function is available. Depending on where the declaration happened, a variable or a function may be available to individual code blocks in JavaScript and not other. We deal with three types of scopes in JavaScript.
Global Scope
When a variable/function is declared in a script tag or a JS file (outside all functions) and accessible from everywhere within that file or the HTML document, it has been declared in the global scope. It is not inside a function or a module.
In the case of a browser, there is a global variable available called window
. You will see developers swapping window.setinterval
or setInterval
without much consequence or side effect. That is because setInterval
is in the global scope. There are plenty of other methods that the browser provides on the window
object.
There are three operators used to declare variables.
const
,let
andvar
. All three can be used to declare global variables, but onlyvar
attaches to thewindow
scope.
Function or Local Scope
When a variable is declared inside a function, it is only available within that function and not outside it. This is because the variable is locally scoped to that function.
const first = "Parwinder"
function sayLastName() {
const last = "Bhagat";
}
console.log(first); // Parwinder
console.log(last); // Reference Error: last is not defined
You can see that the variable last
is not accessible outside the function. I can access it inside the function sayLastName
without an issue.
const first = "Parwinder"
function sayLastName() {
const last = "Bhagat";
console.log(last); // Bhagat
}
sayLastName(); // Remember, I have to call a function to execute the code block in it.
console.log(first); // Parwinder
We read about global variables and how they are available everywhere. This applies to the above snippet too.
const first = "Parwinder"
function sayLastName() {
console.log(first); // Parwinder
const last = "Bhagat";
console.log(last); // Bhagat
}
sayLastName();
console.log(first); // Parwinder
Even though I could not access last
outside the function, I can still access the global variable first
inside the function. This works in JavaScript because when the interpreter reads a variable, it will look for the declaration of that variable in the scope. If the variable is not found in the scope, it goes up one scope. In this example, when we log first
inside sayLastName
, JS engine will look for it in the function scope and then in the global scope. If it doesn’t find it in either, it will go up to the window scope when running JS in a browser. If the variable is not found in any scope going up, we get a reference error thrown.
Block Scope
A block could be defined as a piece of code encapsulated between two curly braces. By this definition, a function is a block. There could be smaller blocks in a function, though. A for loop
or an if
statement inside a function will have its block scope. Block scope helps us to form the small scope segment in code.
The way to create a block scope is by using the const
or let
keyword to declare variables.
function amICool(name) {
let attribute;
if (name === "Parwinder") {
attribute = "cool"
}
return attribute;
}
console.log(amICool("Parwinder")); // cool
console.log(amICool("Bhagat")); // undefined because the name was not "Parwinder"
The above example made the variable attribute
function scope (or the block of the function). We can narrow this scope further.
function amICool(name) {
if (name === "Parwinder") {
let attribute = "cool"
}
return attribute; // Reference error: attribute is not defined
}
console.log(amICool("Parwinder")); // Reference error: attribute is not defined
console.log(amICool("Bhagat")); // This will not run as we ran into an error with the first execution of the function
What happened here? let
made the attribute
variable block-scoped, and this time the block was limited to the if
statement. When we try to return the variable outside the if
statement, it cannot be found or accessed.
As a rule of thumb, use
const
for everything. If the value of the variable changes later, then only switch it tolet
. Usevar
as a last resort.
Lexical Scoping
Wait; what? I thought there were only three types of scopes. Lexical scoping is the scope model that is used by JavaScript. It works by defining the scope where a variable or function is declared and not where it is called from.
const myName = "Parwinder";
function sayMyName() {
console.log(myName);
}
function sayMyNameAgain() {
const myName = "Bhagat";
sayMyName();
}
sayMyNameAgain();
The output will be Parwinder. Why is that:
sayMyNameAgain
is called which in turn callssayMyName
.- Although
sayMyNameAgain
has a function variable calledmyName
with the value of Bhagat, it is never logged. sayMyName
logs the global variablemyName
with the value of Parwinder.
Because sayMyName
executes with the scope of where it was declared.