Details on JavaScript anonymous functions and closures

  • 2020-03-30 04:18:54
  • OfStack

1. Anonymous functions
Functions are one of the most flexible objects in JavaScript, and this is just to show you what anonymous functions are for. Anonymous function: a function that has no name.

1.1 definition of functions. Firstly, the definition of functions is briefly introduced, which can be roughly divided into three ways

The first: this is the most conventional


function double(x){
    return 2 * x;  
}

Second: this method USES the Function constructor and USES both the argument list and the body of the Function as strings, which is inconvenient and not recommended.


var double = new Function('x', 'return 2 * x;');

The third:

Var double = function(x) {return 2* x; }
Note that the function to the right of "=" is an anonymous function that, after being created, is assigned to the variable square.

1.2 creation of anonymous functions

The first way is to define the square function as described above, which is one of the most common ways.

The second way:


(function(x, y){
    alert(x + y); 
})(2, 3);

Here, an anonymous function is created (inside the first parenthesis), and the second parenthesis is used to call the anonymous function and pass in the arguments.

2, closures
Closure is an English word for closure, which is a very important part of JavaScript, because using closures can greatly reduce the amount of code we write, make our code look clearer, and so on.

What a closure means: a closure is simply a nesting of functions, and an inner function can use all the variables of an outer function, even if the outer function has been executed (this involves JavaScript scope chains).

The sample a


function checkClosure(){
    var str = 'rain-man';
    setTimeout(
        function(){ alert(str); } //This is an anonymous function
    , 2000);
}
checkClosure();

This example looks very simple, under the careful analysis of its implementation process there are still many knowledge: checkClosure function execution is instantaneous (perhaps it is only 0.00001 ms), create a variable in function of checkClosure STR, in checkClosure execution after the STR has not been released, this is because the anonymous function being in setTimeout to STR references. STR is not released until the anonymous function inside the function is executed after 2 seconds.

Example 2, code optimization


function forTimeout(x, y){
    alert(x + y);
}
function delay(x , y  , time){
    setTimeout('forTimeout(' +  x + ',' +  y + ')' , time);   
}
/**
 * The above delay Functions are hard to read and hard to write, but using closures can make your code cleaner
 * function delay(x , y , time){
 *     setTimeout(
 *         function(){
 *             forTimeout(x , y)
 *         }         
 *     , time);  
 * }
 */
 

3, for example,
The biggest use of anonymous functions is to create closures (a feature of the JavaScript language), and you can also build namespaces to reduce the use of global variables.

Example 3:


var oEvent = {};
(function(){
    var addEvent = function(){ };
    function removeEvent(){}     oEvent.addEvent = addEvent;
    oEvent.removeEvent = removeEvent;
})();

In this code, the functions addEvent and removeEvent are local variables, but we can use them with the global variable oEvent, which greatly reduces the use of global variables and enhances the security of the web page. We want to use this code: oevent.addevent (document.getelementbyid ('box'), 'click', function(){});

Example 4:


var rainman = (function(x , y){
    return x + y;
})(2 , 3);
/**
 * It can also be written in the following form, as the first parenthesis only helps us read, but the following writing format is not recommended.
 * var rainman = function(x , y){
 *    return x + y;
 * }(2 , 3);
 */

Here we create a variable, rainman, and initialize it to 5 by calling the anonymous function directly, a little trick that is sometimes useful.

Example 5:


var outer = null;
(function(){
    var one = 1;
    function inner (){
        one += 1;
        alert(one);
    }
    outer = inner;
})();
outer();    //2
outer();    //3
outer();    //4

The variable one in this code is a local variable (because it is defined within a function) and is therefore not accessible externally. But here we've created the inner function, which can access the variable one; It also references the global variable outer to inner, so three calls to outer will pop up the increasing result.

4, pay attention to
4.1 closures allow an inner function to refer to a variable in the parent function, but that variable is the final value

Example 6:


/**
 * <body>
 * <ul>
 *     <li>one</li>
 *     <li>two</li>
 *     <li>three</li>
 *     <li>one</li>
 * </ul>
 */ var lists = document.getElementsByTagName('li');
for(var i = 0 , len = lists.length ; i < len ; i++){
    lists[ i ].onmouseover = function(){
        alert(i);   
    };
}

You'll notice when you mouse over each one. Li& Rt. The element always pops up a 4, not the subscript we expected. Why is that? This is covered in the notes (final value). Obviously this explanation is too simple, when the mouseover event calls a listener function, first in the anonymous function(function(){alert(I); }) internal search whether I is defined, the result is no definition; So it will be up to find, find the result is already defined, and the value of I is 4 (circulation after I value); So you end up with a 4 every time.

Solution 1:


var lists = document.getElementsByTagName('li');
for(var i = 0 , len = lists.length ; i < len ; i++){
    (function(index){
        lists[ index ].onmouseover = function(){
            alert(index);   
        };                   
    })(i);
}

Solution 2:


var lists = document.getElementsByTagName('li');
for(var i = 0, len = lists.length; i < len; i++){
    lists[ i ].$$index = i;    //Record the index
by binding the $$index attribute on the Dom element     lists[ i ].onmouseover = function(){
        alert(this.$$index);   
    };
}

Solution 3:


function eventListener(list, index){
    list.onmouseover = function(){
        alert(index);
    };
}
var lists = document.getElementsByTagName('li');
for(var i = 0 , len = lists.length ; i < len ; i++){
    eventListener(lists[ i ] , i);
}

4.2 memory leak

The use of closures is very easy to cause the browser memory leak, in serious cases, the browser will be dead, interested in the word: (link: #)


Related articles: