What is a 'Closure'?

2018-12-31 16:24发布

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

16条回答
人间绝色
2楼-- · 2018-12-31 16:43

From Lua.org:

When a function is written enclosed in another function, it has full access to local variables from the enclosing function; this feature is called lexical scoping. Although that may sound obvious, it is not. Lexical scoping, plus first-class functions, is a powerful concept in a programming language, but few languages support that concept.

查看更多
爱死公子算了
3楼-- · 2018-12-31 16:44

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.

.

查看更多
只若初见
4楼-- · 2018-12-31 16:44

If you are from the Java world, you can compare a closure with a member function of a class. Look at this example

var f=function(){
  var a=7;
  var g=function(){
    return a;
  }
  return g;
}

The function g is a closure: g closes a in. So g can be compared with a member function, a can be compared with a class field, and the function f with a class.

查看更多
旧时光的记忆
5楼-- · 2018-12-31 16:44

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.

查看更多
何处买醉
6楼-- · 2018-12-31 16:45

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.

查看更多
几人难应
7楼-- · 2018-12-31 16:48

Here is another real life example, and using a scripting language popular in games - Lua. I needed to slightly change the way a library function worked to avoid a problem with stdin not being available.

local old_dofile = dofile

function dofile( filename )
  if filename == nil then
    error( 'Can not use default of stdin.' )
  end

  old_dofile( filename )
end

The value of old_dofile disappears when this block of code finishes it's scope (because it's local), however the value has been enclosed in a closure, so the new redefined dofile function CAN access it, or rather a copy stored along with the function as an 'upvalue'.

查看更多
登录 后发表回答