Javascript closure

Created By: chatGPT

JavaScript closures are a fundamental concept that allows a function to maintain access to its lexical scope, even when the function is executed outside that scope. This means that inner functions can access variables of their outer function even after the outer function has completed its execution.
function outerFunction() {
    let outerVariable = 'I am from outer function';

    function innerFunction() {
        console.log(outerVariable);
    }

    return innerFunction;
}

const myInnerFunction = outerFunction();
myInnerFunction(); // Logs: I am from outer function
In the example above, outerFunction defines a variable called outerVariable and an inner function innerFunction. When outerFunction is called, it returns innerFunction. Even though outerFunction has finished executing, innerFunction retains access to outerVariable due to the closure created.
function makeCounter() {
    let count = 0;

    return {
        increment: function() {
            count++;
            return count;
        },
        decrement: function() {
            count--;
            return count;
        },
        getCount: function() {
            return count;
        }
    };
}

const counter = makeCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.decrement()); // 1
console.log(counter.getCount()); // 1
In this makeCounter example, we encapsulate the count variable within the closure. The returned object has methods to increment, decrement, and retrieve the value of count. This way, the count variable is not directly accessible from outside, ensuring that it's manipulated only through the provided functions.
function createMultiplier(multiplier) {
    return function(number) {
        return number * multiplier;
    };
}

const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
The createMultiplier function demonstrates how closures can capture particular values. Each call to createMultiplier generates a new function that multiplies its input by the multiplier provided at the time of creation. Thus, the returned functions have unique environments storing the specific multiplier.
const makeCounter = () => {
    let count = 0;

    return {
        increment: () => ++count,
        decrement: () => --count,
        getCount: () => count
    };
};

const counter = makeCounter();
console.log(counter.increment()); // 1
console.log(counter.getCount()); // 1
Here we see the use of arrow functions in the makeCounter example. Arrow functions also create closures, providing a more concise syntax while maintaining access to the surrounding context. They are particularly handy for methods in objects that belong to a closure.
function countdown(num) {
    return function() {
        if (num > 0) {
            console.log(num);
            num--;
            return countdown(num);
        } else {
            console.log('Countdown Finished!');
        }
    };
}

const startCountdown = countdown(5);
startCountdown();
startCountdown();
startCountdown();
startCountdown();
startCountdown();
startCountdown(); // Countdown Finished!
The countdown function shows how closures can keep state over multiple calls. Each time you invoke startCountdown, it retains the value of num within the closure, allowing the countdown process to continue until it reaches zero. This illustrates the power of closures in maintaining state in JavaScript.
const adder = (x) => (y) => x + y;

const add5 = adder(5);
console.log(add5(3)); // 8
console.log(add5(10)); // 15
console.log(adder(10)(5)); // 15
Introduction And SetupVariablesData TypesMethodsControl FlowFunctionsOperatorsData StructuresCommentsSyntaxEvent HandlingError HandlingPrimitive Data TypesReference Data TypesConstLetVarStringNumberBooleanNullUndefinedSymbolObjectArrayTemplate LiteralsArrow FunctionsRegular FunctionsCallApplyBindAsync FunctionsPromisesCallback FunctionsIf StatementElse StatementSwitch StatementFor LoopWhile LoopDo While LoopFor EachBreak StatementContinue StatementTry CatchThrowFinallyScopeClosureThis KeywordPrototypesInheritanceConstructor FunctionsClass SyntaxStatic MethodsGettersSettersSpread OperatorRest OperatorDestructuring AssignmentMap MethodFilter MethodReduce MethodEvent ListenersDom ManipulationInnerHTMLQuerySelectorAddEventListenerPreventDefaultStopPropagationTimeoutsIntervalsJsonLocal StorageSession StorageRegexMath ObjectDate ObjectString MethodsArray MethodsObject MethodsDeep CloningShallow CloningCallback HellPromise ChainingAsync AwaitMap Vs ForEachFilter Vs ReduceNullish Coalescing OperatorOptional ChainingTypeof OperatorInstanceof OperatorStrict EqualityLoose Equality