Scopes and Closures
In JavaScript scope and closure are two fundamental concepts, scope determines the accessibility of variables, while closures are functions that keep certain variables safe and accessible even after their original functions have finished running.
Scope
In JavaScript, scope defines where variables can be accessed or referenced. While some variables can be accessed from anywhere within a program, and some variables may only be available in a specific block of code.
Types of Scope:
Global Scope
Variables declared outside of any function with var, let and const keyword are in Global Scope. Those variables can be accessed from any part of the code, including within any functions.
Example:
const flower = 'Rose';
function favouriteFlower(){
return flower + ' is my favourite flower'
};
console.log(favouriteFlower()); //output:Rose is my favourite flower
In above code, variable flower is declared outside of the function, and we have accessed it within the function.
Local Scope
Variables declared inside a function with 'var' keyword are in local scope, also known as function scope. Those variables are only accessible within the function.
Example:
function favouriteFlower(){
var flower = 'Rose';
return flower + ' is my favourite flower'
};
console.log(favouriteFlower()); //Output: Rose is my favourite flower
console.log(`${flower} is my favourite flower`); //error:flower is not defined
In above code, variable flower is declared inside the function, thus we can access it within the function, but we we cannot access it outside the function, as it throws the error.
Block Scope
Variables declared with the 'let' and 'const' keywords have block scope. They are only accessible within the block of code in which they are declared.
Example:
{
let flower = 'Rose';
console.log(flower); //Prints Rose is my favourite flower
}
console.log(flower); //Error: flower is not defined
In example, variable is declared inside the block with let keyword, and we have accessed it within block, but it is not accessible outside the block.
Closure
Closure allows the inner function to remember the state of its parent function, even if the parent function has finished executing.
Creating Closure
Closures are created when an inner function refers to the variables from its outer function.
function greetingGenerator(greeting) {
function greet(name) {
console.log(greeting + ', ' + name + '!');
}
return greet;
}
var greetWithHello = greetingGenerator('Hello');
var greetWithGoodMorning = greetingGenerator('Good morning');
greetWithHello('Bob'); // Output: Hello, Bob!
greetWithGoodMorning('John'); // Output: Good morning, John!
In above example, greetingGenerator is a function which takes a greeting parameter. Inside greetingGenerator ,there's an inner function greet that has access to the greeting parameter. The outer function returns the inner function, which creates closure. This closure remembers the greeting value even after greetingGenerator has finished execution. Two closures (greetWithHello and greetWithGoodMorning) are created with different greetings. When the closures are called with different names, they use the remembered greetings to generate personalized greetings.