JavaScript tamping basic Series (ii): Closures

Source: Internet
Author: User
Tags closure

?? In JavaScript the function is a one-class citizen . The so-called one-class citizen refers to functions like other objects, very common, can be in the array of functions exist, as parameters passed, assigned to variables and other operations. When a function is called externally as the return value of another function, it is called a closure, as is the lexical scope accessible when the function is called inside the function.

One, what is closures

?? Closures are defined in many areas, such as closures, which are functions that have access to variables in another function scope. Or a more fundamental definition: A function object can be associated with a scope chain, and the variables inside the function body can be stored within the scope of the function, meaning that the function variable can be hidden within the scope chain and appears to be a function that "wraps" the variable. Personal comparisons tend to be a popular definition: A closure is a function that remembers and accesses its lexical scope, even when the function is executed outside its lexical scope .

?? As shown in the following code, the Execute test function returns the print function and executes the print function under the global scope, but the print function remembers its scope and can refer to its local variable for the outer function test when it is defined.

var=1;      functiontest (){    var=2;    functionprint (){        console.log(a)    }    return print}      test// 2

?? Because there is no concept of block-level scope in JavaScript, the immediate execution function (iife) is often used to simulate block-level scopes.

var=1;(functionIIFE(){    var=2;    console.log( a );// 2})();console.log( a );// 1

?? In an academic sense, every function in JavaScript is a closure: they are all objects, and they are all linked to the scope chain. However, from the perspective that closures can be called from outside the lexical scope and can access lexical scopes,Iife is not a closure. As shown in the following code: When the function test executes, finding the variable A is a step down the scope chain and does not reflect the characteristics of the closure.

(functionIIFE(){    var=1;    functiontest{        console.log(a)    }    test// 1})();
Second, the principle of closure

?? When a function executes, the scope chain of its outer function is copied first (if the function is a reference to only one global object in the scope chain in the Global environment), assign to a special intrinsic property (i.e. [[Scope]]). The variable object of the function is then initialized with the values of this, arguments, and other named arguments, and a reference to the variable object is added to the function's scope chain.

?? When the function is finished, the scope chain of the function is deleted, and the corresponding variable object does not have a reference to the scope chain to be garbage collected. But the case of closures is different, although the function is executed, but the function returns an intrinsic function that has a reference to the function variable object on the scope chain of the inner function, so the function is executed but the variable object of the function is not destroyed. You can still access variables on the function variable object by returning an intrinsic function.

?? It is important to note that a closure can only get the last value that contains any variable in the function. Defining a function expression in a for loop is particularly true of this. As shown in the following code, we want the function array returned by the test function to hold the function that can print its subscript, but the result is the full number 10. The reason for this is that we mistakenly think that I will be copied once per loop, in fact nested functions do not copy the private members of the scope and do not generate a static snapshot of the bound variable. The function array returned by the test function refers to the same variable i, the variable i is shared, and the value of I at the end of the loop is 10, so the result of any function in the execution function array is to print out the number 10.

function   Test  () { var  arr =  [] for  (var  i=  0  ;  I<  10   I++ ) { arr[i] =  function< /span> () { console .  Log  (i) }  }  return  arr}  var  print =  test  () print[< Span class= "DV" >2 ] () //  

?? We have improved the code to avoid the data sharing situation. In the following code, instead of assigning a closure to an array directly, the function temp is defined, and the return value after the TEMP function is executed is assigned to the array. Because the function arguments are passed by value , a copy of the argument I is copied each time the temp is called, and the functions stored in the function array have copies of their respective variable I time periods, breaking the original shared data I, and therefore being able to return their different values.

function Test(){    varArr=[] for(varI=0;I<Ten;I++){        function Temp(j){            return function(){                Console.Log(j)}        }Arr[i]= Temp(i)}    returnArr}varPrint= Test() print[2]()//2
Third, the use of closures

?? Closures are ubiquitous in JavaScript code and are mainly used in modular mode as well as currying in functional programming.

1. Module mode

?? Before ES6, the language structure used to support modules was not defined in JavaScript, but it was easy to implement code modularity with closures. The variables defined in the function are private to the function, cannot be accessed directly outside the function and modify variables inside the function, but the internal functions returned by the function are able to access the variables, and the internal functions returned are called module patterns , just like the common interfaces exposed in the outer bounds. As shown in the following code:

function Module(){    varValue= 0    function Get(){        returnValue}    function Set(Val){Value=Val}    return {        Get:Get,        Set:Set}}varTest= Module()varModu= Module()Console.Log(Test.Get())//0Test.Set(1)Console.Log(Modu.Get())//0Console.Log(Test.Get())//1Test.Set(Ten)Console.Log(Modu.Get())//0Console.Log(Test.Get())//Ten

?? In module mode , the return value of a module can be an object, or it can be just an intrinsic function. The module is just a function, so it can receive parameters. From the code above, it can be seen that each execution of a function returns a closed packet that is independent of each other and does not affect each other. The general module is used in the case of a singleton mode , can be implemented with Iife , as shown in the following code:

varModule=(function Module(){        varValue= 0        function Get(){            returnValue}        function Set(Val){Value=Val}        return {            Get:Get,            Set:Set}    })()Console.Log(Module.Get())//0Module.Set(1)Console.Log(Module.Get())//1Module.Set(Ten)Console.Log(Module.Get())//Ten

?? In summary, the module requires two key properties: 1, as a function of the module is called to execute. 2. The return value of the function is used at least for a reference to an intrinsic function.

2, currying

?? currying is a technique that transforms a function that accepts multiple parameters into a function that takes a single parameter (the first parameter of the original function) and returns a new function that accepts the remaining arguments and returns the result. The advantage of curry is that it improves the applicability and can realize the effect of parameter multiplexing. As shown in the following code:

function Test(A,B,C{    returnA+B+C}Console.Log(Test(1,2,3))//6function _test(a){    return function(b){        return function(c){            returnA+B+C}    }}Console.Log(_test(1)(2)(3))//6

?? The _test function uses a function closure to achieve the effect of curry, and each invocation of a function closure can access the last parameter passed in and access it. For example, libraries such as lodash encapsulate generic curry functions, pass in a common function, and return an equivalent function of the curry function, which is detailed in subsequent articles in this series.

Iv. Summary

?? A closure is a function that remembers and accesses its lexical scope, even when the function is executed outside its lexical scope. Once the function is executed, the corresponding variable object does not have a reference to the scope chain as garbage is recycled, but if a closure situation becomes different, the scope chain of the closure remains a reference to the variable object of the external function, so the variable object of the external function is not destroyed and the closure is still able to access the variables of the external function.

?? In JavaScript, there is no syntax for modules (before ES6), and closures can be used to implement module patterns . In functional programming, currying is very common and can be achieved by using closures.

If you need to reprint, please indicate the source: https://www.cnblogs.com/lidengfeng/p/9158827.html

JavaScript tamping basic Series (ii): Closures

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.