In-depth understanding of the nine usage scenarios for JS closures

1 Return value (most commonly used)

  // Return name as a closure.
function fn(){
        let name = "hello"
        return function(){
            returnname; }}let func = fn(); // call the function
console.log(func());// Call again, print hello
Copy the code

2 function assignment

Set the value of the fn2 function in a closure that memorizes the name property and prints Hello

    let fn2;
    function fn(){
        let name= "hello"
        // Assign the function to fn2
        fn2 = function(){
            return name;
        }
    }

    fn() // Perform the assignment first
    console.log(fn2());// Execute output fn2, which is hello
Copy the code

3 Function Parameters

Use closures to return a function, take that function as an argument to another function, execute that function inside another function, and finally print Hello

function fn(){
    let name = "hello"
    return function callback(){
        returnname; }}let fn1 = fn() // The callback function assigns the return value to fn1

function fn2(f){
    // Pass the function as an argument
    console.log(f()); // Execute the function and print it
    
}

fn2(fn1)  // Call the function
Copy the code

4.IIFE (self-executing function)

Passing fn1 as an argument to fn2 directly from the self-executing function also results in Hello

(function(){
   let name = "hello";
   let fn1 = function(){
       return name;
   }
   // Call fn2 directly from the self-executing function, passing fn1 as an argument
    fn2(fn1)
})()

function fn2(f){
    // Function groups are passed in as arguments
    console.log(f());// Execute the function and print it
    
}
Copy the code

5 Loop assignment

   // Execute once per second, output 1-10 respectively
    for(let i = 1; i <=10; i++){
        (function (j) {
            setTimeout(function() {
                console.log(j);
                
            },j*1000)
        })(i)// I is passed as an argument
    }
Copy the code

6 getter and setter

By first printing Hello and then world with setter, you can encapsulate it as a public method, preventing unwanted properties and functions from being exposed externally.

 function fn() {
     let name = "hello"
     setName = function (n) {
         name = n;
     }
     getName = function(){
         return name;
     }

 // return setName, getName as properties of the object
     return {
        setName:setName,
        getName:getName
        / / short
        //setName,getName}}let fn1 = fn()SetName and getName are two functions
 console.log(fn1.getName());//getter
 fn1.setName('world');// setters modify the name inside closures
 console.log(fn1.getName());//getter
 
Copy the code

7. Iterators (perform a function once to fetch a value down)

let arr = ["aa".'bb'.'cc']
function increment(arr){
    let i = 0;
    return function(){
         // This function returns the element of the array arr that corresponds to the I subscript each time it is executed
        return arr[i++] || "Array traversal is complete"}}let next = increment(arr);
console.log(next()); //aa
console.log(next());//bb
console.log(next());//cc
console.log(next());// The array values are already iterated
Copy the code

8 First distinction (same argument, function will not be executed twice)

let fn = (function(){
 let arr=[];// An array for caching
 return function(val){
     if(arr.indexOf(val)==-1) {// If the command is not in the cache, the command needs to be executed
         arr.push(val);// Push the parameter into the cache array
         console.log('Function executed',arr);
         // Write the function you want to execute here
     }else{
         console.log('This function does not need to be executed.');
     }
     console.log('After the function is called, print it to see the cached array:',arr);
 }
})();

fn(10);
fn(10);
fn(1000);
fn(200);
fn(1000);
Copy the code

The result is as follows:

You can obviously see that the first execution is saved and the second execution is direct fetch.

9 cache

For example, the sum operation, if there is no cache, each call will be repeated calculation, using the cache has been executed to find, directly returned, no need to recalculate

let fn = (function(){
    let cache = {} 
    let calc = function (arr) {
        let sum = 0;
        for (let i = 0; i < arr.length; i++) {
           sum+=arr[i]
            
        }
        return sum;
    }
    return function() {
        let args = Array.prototype.slice.call(arguments.0);
        let key = args.join(', ')
        let result , total = cache[key];
        if(total){
            console.log('Fetch from cache:',cache)// Print for easy viewing
          result = total;
            
        }else{
          // recalculate, store in cache and assign to result
          result = cache[key]=calc(args);
          console.log('Store in cache:',cache)// Print for easy viewing
      }
      return result;
    }
})();
fn(1.2.3.4.5);
fn(1.2.3.4.5);
fn(1.2.3.4.5.6);
fn(1.2.3.4.5.8);
fn(1.2.3.4.5.6);

Copy the code

The output

Refer to the article