What is a 'Closure'?

前端 未结 23 1135
星月不相逢
星月不相逢 2020-11-22 08:02

I asked a question about Currying and closures were mentioned. What is a closure? How does it relate to currying?

相关标签:
23条回答
  • 2020-11-22 08:41

    Kyle's answer is pretty good. I think the only additional clarification is that the closure is basically a snapshot of the stack at the point that the lambda function is created. Then when the function is re-executed the stack is restored to that state before executing the function. Thus as Kyle mentions, that hidden value (count) is available when the lambda function executes.

    0 讨论(0)
  • 2020-11-22 08:42

    I'll give an example (in JavaScript):

    function makeCounter () {
      var count = 0;
      return function () {
        count += 1;
        return count;
      }
    }
    
    var x = makeCounter();
    
    x(); returns 1
    
    x(); returns 2
    
    ...etc...
    

    What this function, makeCounter, does is it returns a function, which we've called x, that will count up by one each time its called. Since we're not providing any parameters to x it must somehow remember the count. It knows where to find it based on what's called lexical scoping - it must look to the spot where it's defined to find the value. This "hidden" value is what is called a closure.

    Here is my currying example again:

    function add (a) {
      return function (b) {
        return a + b;
      }
    }
    
    var add3 = add(3);
    
    add3(4); returns 7
    

    What you can see is that when you call add with the parameter a (which is 3), that value is contained in the closure of the returned function that we're defining to be add3. That way, when we call add3 it knows where to find the a value to perform the addition.

    0 讨论(0)
  • 2020-11-22 08:43

    Currying : It allows you to partially evaluate a function by only passing in a subset of its arguments. Consider this:

    function multiply (x, y) {
      return x * y;
    }
    
    const double = multiply.bind(null, 2);
    
    const eight = double(4);
    
    eight == 8;
    

    Closure: A closure is nothing more than accessing a variable outside of a function's scope. It is important to remember that a function inside a function or a nested function isn't a closure. Closures are always used when need to access the variables outside the function scope.

    function apple(x){
       function google(y,z) {
        console.log(x*y);
       }
       google(7,2);
    }
    
    apple(3);
    
    // the answer here will be 21
    
    0 讨论(0)
  • 2020-11-22 08:50

    In short, function pointer is just a pointer to a location in the program code base (like program counter). Whereas Closure = Function pointer + Stack frame.

    .

    0 讨论(0)
  • 2020-11-22 08:50

    Please have a look below code to understand closure in more deep:

            for(var i=0; i< 5; i++){            
                setTimeout(function(){
                    console.log(i);
                }, 1000);                        
            }
    

    Here what will be output? 0,1,2,3,4 not that will be 5,5,5,5,5 because of closure

    So how it will solve? Answer is below:

           for(var i=0; i< 5; i++){
               (function(j){     //using IIFE           
                    setTimeout(function(){
                                   console.log(j);
                               },1000);
                })(i);          
            }
    

    Let me simple explain, when a function created nothing happen until it called so for loop in 1st code called 5 times but not called immediately so when it called i.e after 1 second and also this is asynchronous so before this for loop finished and store value 5 in var i and finally execute setTimeout function five time and print 5,5,5,5,5

    Here how it solve using IIFE i.e Immediate Invoking Function Expression

           (function(j){  //i is passed here           
                setTimeout(function(){
                               console.log(j);
                           },1000);
            })(i);  //look here it called immediate that is store i=0 for 1st loop, i=1 for 2nd loop, and so on and print 0,1,2,3,4
    

    For more, please understand execution context to understand closure.

    • There is one more solution to solve this using let (ES6 feature) but under the hood above function is worked

       for(let i=0; i< 5; i++){           
           setTimeout(function(){
                          console.log(i);
                      },1000);                        
       }
      
      Output: 0,1,2,3,4
      

    => More explanation:

    In memory, when for loop execute picture make like below:

    Loop 1)

         setTimeout(function(){
                        console.log(i);
                    },1000);  
    

    Loop 2)

         setTimeout(function(){
                        console.log(i);
                    },1000); 
    

    Loop 3)

         setTimeout(function(){
                        console.log(i);
                    },1000); 
    

    Loop 4)

         setTimeout(function(){
                        console.log(i);
                    },1000); 
    

    Loop 5)

         setTimeout(function(){
                        console.log(i);
                    },1000);  
    

    Here i is not executed and then after complete loop, var i stored value 5 in memory but it's scope is always visible in it's children function so when function execute inside setTimeout out five time it prints 5,5,5,5,5

    so to resolve this use IIFE as explain above.

    0 讨论(0)
  • 2020-11-22 08:50

    Closures provide JavaScript with state.

    State in programming simply means remembering things.

    Example

    var a = 0;
    
    a = a + 1; // => 1
    a = a + 1; // => 2
    a = a + 1; // => 3
    

    In the case above, state is stored in the variable "a". We follow by adding 1 to "a" several times. We can only do that because we are able to "remember" the value. The state holder, "a", holds that value in memory.

    Often, in programming languages, you want to keep track of things, remember information and access it at a later time.

    This, in other languages, is commonly accomplished through the use of classes. A class, just like variables, keeps track of its state. And instances of that class, in turns, also have state within them. State simply means information that you can store and retrieve later.

    Example

    class Bread {
      constructor (weight) {
        this.weight = weight;
      }
    
      render () {
        return `My weight is ${this.weight}!`;
      }
    }
    

    How can we access "weight" from within the "render" method? Well, thanks to state. Each instance of the class Bread can render its own weight by reading it from the "state", a place in memory where we could store that information.

    Now, JavaScript is a very unique language which historically does not have classes (it now does, but under the hood there's only functions and variables) so Closures provide a way for JavaScript to remember things and access them later.

    Example

    var n = 0;
    var count = function () {
      n = n + 1;
      return n;
    };
    
    count(); // # 1
    count(); // # 2
    count(); // # 3
    

    The example above achieved the goal of "keeping state" with a variable. This is great! However, this has the disadvantage that the variable (the "state" holder) is now exposed. We can do better. We can use Closures.

    Example

    var countGenerator = function () {
      var n = 0;
      var count = function () {
        n = n + 1;
        return n;
      };
    
      return count;
    };
    
    var count = countGenerator();
    count(); // # 1
    count(); // # 2
    count(); // # 3
    

    This is fantastic.

    Now our "count" function can count. It is only able to do so because it can "hold" state. The state in this case is the variable "n". This variable is now closed. Closed in time and space. In time because you won't ever be able to recover it, change it, assign it a value or interact directly with it. In space because it's geographically nested within the "countGenerator" function.

    Why is this fantastic? Because without involving any other sophisticated and complicated tool (e.g. classes, methods, instances, etc) we are able to 1. conceal 2. control from a distance

    We conceal the state, the variable "n", which makes it a private variable! We also have created an API that can control this variable in a pre-defined way. In particular, we can call the API like so "count()" and that adds 1 to "n" from a "distance". In no way, shape or form anyone will ever be able to access "n" except through the API.

    JavaScript is truly amazing in its simplicity.

    Closures are a big part of why this is.

    0 讨论(0)
提交回复
热议问题