02 - Higher Order Functions & Closures


//Higher order functions:-
//========================
function fun() {
    console.log('inside fun');
    
    let x = 0;
    
    function innerFun() {
        x++;
        console.log(x);
    }

    return innerFun;

}

let f = fun(); //Output: inside fun

f(); //Output: 1
f(); //Output: 2
f(); //Output: 3
f(); //Output: 4
f(); //Output: 5

console.log('\n\n\n\n');

//Closures:-
//==========
console.log('Closures:\n\n');

var add = (function () {
  var counter = 0;
  return function () {counter += 1; return counter}
})();

console.log(add());
console.log(add());
console.log(add());

// the counter is now 3

//What does this mean?
//The variable add is assigned to the return value of a self-invoking function.
//The self-invoking function only runs once. It sets the counter to zero (0), and returns a function expression.
//This way add becomes a function. The "wonderful" part is that it can access the counter in the parent scope.
//This is called a JavaScript closure. It makes it possible for a function to have "private" variables.
//The counter is protected by the scope of the anonymous function, and can only be changed using the add function.

//=>A closure is a function having access to the parent scope, even after the parent function has closed.