What is a closure package? ——— > is a function, a function that can access data inside other functions.
Chestnut One:
function foo () { var a = 1;} function fn () { console.log (a); // error, because there is no access to A's }
function foo () { var a = 1; function fn () { console.log (a); // This allows access to A's The returnFN;//FN is a closure, and its invocation in Foo is meaningless, so it is returned to the outside to determine the timing of the call, making it more meaningful to create the closure FN when an external function is executed }
First, the basic structure of closures: 1. Define the outer function, 2. Define an intrinsic function, 3. The inner function refers to the data defined by the outer function, and 4. The inner layer function is used as the return value of the outer function;
function outer () { var data = {name: 'xiaoming '};//The internal data of the outer function is cached in memory function inner () { return data; } return inner;} var closure1 = outer ();//After you get the closure you can decide when to execute it;Console.log (Closure1 ()); var closure2 = outer (); Console.log (Closure2 = = Closure1);//false, because two outer functions were called, so that two data objects were created, so two closed packets were accessed in memory with different addresses; var D1 = Closure1 (); Var D2 = Closure1 (); Console.log (D1 = = D2);//true
a closure is a data sharing, two closures is two data, so you do not have to create two closures (that is, to execute two external functions);
Closure Application: Click each Li to print out each Li corresponding number
<ul> <li>0</li> <li>1</li> <li>2</li> <li>3 </li> <li>4</li></ul><script> var lists = document.getElementsByTagName ("Li"); var i = 0, = lists.length; for (; i<l; i++) { function() {//// for each Li binds a click event console.log (i); The results are printed 5, because when I click on Li, I has become 5 } }</script>
Use closures to solve problems:
var lists = document.getElementsByTagName ("li"); var i = 0, = lists.length; for (; i<l; i++) { = (function (i) {//2.) receives the parameter inside the outer function and caches it as internal data in memory function fn () { Console.log (i);//3. Here i is the inner data of the outer function, respectively, 0,1,2,3,4 } return FN;//4. Returns to the external as a handler for the Click event, triggering the execution of the closure when a click event occurs, At that time the printed i is the I value of the outer function cache }) (i);//1. Self-executing function, the global variable i is passed into the outer function sequentially }
Iife (Execute function expression immediately):( Function () {}) ();!function () {} ();+function () {} ();
Second, the role of closure 1. Avoid global contamination
var function () {}; // define the things global variable $ // But if a jquery.js is introduced before this, then the $ function of jquery will be overwritten by this global variable $
In the daily development, this kind of thing will be very common, because you can not guarantee that other developers will define what kind of variable, then a page first introduced in the JS file of the variable is likely to be defined in the following JS file with the same name of the global variable coverage; In addition, the global variable life cycle exists with the existence of the page, the page , the variable will always consume memory and consume performance, so it is not recommended to use global variables too much;
function outer () {// $ and attr in the outer function are actually equivalent to global variables, as long as the closure exists, these variables will always be var $ = function () {}; var attr = 10; return {// The $ and attr in this will not be contaminated by any other global variables function () { return attr; }}} var query = outer (); query.$ ("divs"); Console.log (query.getattr);
In the chestnuts above, the $ and attr variables are placed inside an outer function as internal data, and the closure (means $ and getattr two methods) is returned and assigned to a global variable query, which can greatly reduce the probability of global pollution when the global variables are large.
2. Cache data 1) can be cached with global variables ——— > life cycle is too long cost performance 2) use Cookie\localstorage and so on cache-->io stream not in-memory access speed 3) with closures to cache For a chestnut: Fibonancci the nth value of the sequence number
function fib (n) { if (n < 1) { thrownew Error ("Value not Increct"); } if (n = = 1 | | n = = 2) { return 1; Else { return fib (n-1) + fib (n-2); }}
The process plot for the FIB (6) value is obtained recursively:
There are too many repetitions, and when the required values are large, the performance is particularly low; the closure is used to optimize:
functionCreatefib () {varcache = [, 1, 1];//Store the calculated results and the computed results are cached in memory for the next direct use return function(n) {//The function of the closure is to obtain the value of the n term, and the closure function can get the value of those items in the cache that have already computed the result; varres = cache[n];//If this item is in the cache, use the if(!res) {//If you don't have a value for this item, you need to recalculate res = Cache[n] = fib (n-1) + fib (n-2);//The value of the nth item is the and of his first two values, still recursive, here the difference is that the calculated value does not have to be recalculated, but directly take the results in the cache, in addition to this calculation is completed, The result is also stored in the cache for the next use, and the value is assigned to the RES variable for return; } returnRes; };}var fib = Createfib ();//The need for recursion is that the fib is the closure rather than the outer function createfib, because the closure is the real execution of the nth value of the function function, and the role of the outer function is to use internal data to do the cache;Console.log (FIB (50));//greatly improve computational efficiency
The procedure for calculating the FIB (6) value in a closed package is as follows:
3, the higher order function satisfies one of the following conditions is the higher order function
- function type as parameter (for example, foreach, Map,filter, callback function in ES5)
- return function (Closure)
For a chestnut: staff wages (basic salary + Commission), general Staff basic Salary 1000, commission everyone is not the same, the manager base salary 2000, the commission of each manager is different;
function Calsalary (Base, ext) { var base = base * +; repeat return base + ext for each calculation ;} var = calsalary (S1); var = calsalary (S2);::var p1 = calsalary (+); var p2 = calsalary (2000, 300);
Like this cardinality calculation, you can use closures to optimize:
functionCalsalary (base) {varBase = Base * 10 + 20;//once computed as a cache return function(EXT) {returnBase + ext;//The base in the cache is taken directly here, eliminating a lot of repetitive calculations }}vars = calsalary (1000);//get the closures .varS1 = s (500);//only closures are executed at a timevarS2 = s (1000);varp = calsalary (2000);//create another closure because the shared data is differentvarP1 = P (500);//same time only closures are executedvarP2 = P (500);
4, callback function parameter: Chestnut: to the timer callback function to pass the parameter, realizes div1 seconds after the background turns red;
SetTimeout (function(color) {// executes functions immediately, receives a color parameter, eases the presence of in-memory var div = document.getElementById ("div"); return function () {// return a function as a delay callback function, execute div.style.background = color after 1 seconds ) (' red '), 1000)
Extended:
The role of JavaScript closures and closures