// Closures
// In JavaScript, closure is one of the widely discussed and important concepts.
// A closure is a function that has access to the variable from another function’s scope which is accomplished by creating a function inside a function. As defined on MDN:
// “Closures are functions that refer to independent (free) variables. In other words, the function defined in the closure ‘remembers’ the environment in which it was created.”
// In JavaScript, closures are created every time a function is created, at function creation time. Most JavaScript developers use closure consciously or unconsciously — but knowing closure provides better control over the code when using them.
// Example:
function Spellname(name) {
var greet = "Hi, " + name + "!";
var sName = function() {
var welc = greet + " Good Morning!";
console.log(greet);
};
return sName;
}
var Myname = SpellName("Nishi");
Myname(); // Hi, Nishi. Good Morning!
// In the above example, the function sName() is closure; it has its own local scope (with variable welc) and also has access to the outer function’s scope. After the execution of Spellname(), the scope will not be destroyed and the function sName() will still have access to it.
// A closure is a function having access to the parent scope,
// even after the parent function has popped.
function greeting() {
let message = 'Hi';
function sayHi() {
console.log(message);
}
return sayHi;
}
let hi = greeting();
hi(); // still can access the message variable
function foo() {
const secret = Math.trunc(Math.random() * 100)
return function inner() {
console.log(`The secret number is ${secret}.`)
}
}
const f = foo() // `secret` is not directly accessible from outside `foo`
f() // The only way to retrieve `secret`, is to invoke `f`
Run code snippet
Closures are related and often confused with lambda functions.
The 2 concepts are wonderfully explained and distinguished
in this StackOverflow answer :
https://stackoverflow.com/a/36878651/13574304
function OuterFunction() {
var outerVariable = 100;
function InnerFunction() {
alert(outerVariable);
}
return InnerFunction;
}
var innerFunc = OuterFunction();
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
//=====
//add5 and add10 are both closures.
//They share the same function body definition, but store different lexical environments.
//In add5's lexical environment, x is 5, while in the lexical environment for add10, x is 10.
function Counter() {
var counter = 0;
alert("XXXXX");
function increaseCounter()
{
return counter +=1;
}
return increaseCounter;
}
/***/
const counter = new Counter();
console.log(counter());
console.log(counter());
/*note that alert("XXXX") only executes once*/
/*think of counter() = new Counter() declaration as storing the value of ONE Counter function execution and
the remaining times you use counter(), you reexecute only the returned function*/
/*use counter() instead of Counter() if you want alert("XXXX") to execute only once AND for you to be able to return an actual value otherwise you only console.log a function and alert executes multiple times*/
// Closures
//Almost mystical like feature that many developers fail to fully understand.
//We cannot create closures manually like how we create arrays and functions.
//Rather closures happen in certain situations. We just need to recognize
//those situations.
//Example:
const secureBooking = function () {
let passengerCount = 0; //Variable of the secureBooking Function
//returns a function
return function () {
passengerCount++; //Adding to the passengerCount
console.log(passengerCount);
};
};
const book = secureBooking(); //capture that function
book();
//In the above example we have a function called secureBooking
//That function returns another function, which we stored in book variable
//We then call the book() function and it adds to the passengerCount.
//But you may be wondering? How can it add to the passengerCount
//if the secureBooking has finished executing, shouldn't it not exist?
//This works because all functions have access to the variable environment
// in which they were created in. Meaning since secureBooking created
// the function which we stored in book. The book function now has
// access to the variable environment of secureBooking function.
outer = function() {
var a = 1;
var inner = function() {
console.log(a);
}
return inner; // this returns a function
}
var fnc = outer(); // execute outer to get inner
fnc();
/*
A lexical environment is part of every execution context (stack frame) and is a map between identifiers (i.e. local variable names) and values.
Every function in JavaScript maintains a reference to its outer lexical environment. This reference is used to configure the execution context created when a function is invoked.
This reference enables code inside the function to "see" variables declared outside the function, regardless of when and where the function is called.
If a function was called by a function, which in turn was called by another function, then a chain of references to outer lexical environments is created.
This chain is called the scope chain.
In the following code, inner forms a closure with the lexical environment of the execution context created when foo is invoked, closing over variable secret:
*/
function foo() {
const secret = Math.trunc(Math.random() * 100)
return function inner() {
console.log(`The secret number is ${secret}.`)
}
}
const f = foo() // `secret` is not directly accessible from outside `foo`
f() // The only way to retrieve `secret`, is to invoke `f`
Run code snippet
// javascript closure example
// outer function
function greet() {
// variable defined outside the inner function
let name = 'John';
// inner function
function displayName() {
// accessing name variable
return 'Hi' + ' ' + name;
}
return displayName;
}
const g1 = greet();
console.log(g1); // returns the function definition
console.log(g1()); // returns the value
var returns_a_func = function () {
var word = 'I can see inside ' function sentence(){ var word2 = 'I can also see outside. ' console.log(word + 'and ' + word2) } return sentence;
}var finalSentence = returns_a_func()finalSentence()
/*A closure is the combination of a function bundled together (enclosed) with references
to its surrounding state (the lexical environment). In other words, a closure gives you
access to an outer function’s scope from an inner function. In JavaScript, closures are
created every time a function is created, at function creation time.*/
function init() {
var name = 'Mozilla'; // name is a local variable created by init
function displayName() { // displayName() is the inner function, a closure
alert(name); // use variable declared in the parent function
}
displayName();
}
init();