JavaScript anonymous functions and closures introduction _javascript tips

Source: Internet
Author: User
Tags closure garbage collection

anonymous function: A function without a name;
Closures: Functions that can access variables in a function scope;

An anonymous function

normal function
  box () {            //function name is box;
    Return ' Lee ';
  Box ();                =>lee; Call function;
Anonymous functions function
  () {              //anonymous function, error;
    Return ' Lee ';
Self-executing by expression
  (function (name) {
    console.log (name);        =>lee;
  }) ("Lee");              "()" means that the function is executed and can be passed;
Assign the anonymous function to the variable
  var box = function () {        //Assign the anonymous function to the variable;
    Return ' Lee ';
  Console.log (Box ());         The calling method is similar to the function call;
anonymous functions in Functions function
  box () {return function
    (name) {      //function anonymous functions, resulting in closures;
      return name;
  }; Console.log (Box () ("Lee");      function box () calls the anonymous function, and passes the argument;

Two closures

Closure: A function that has access to a variable in the scope of another function;
A common way to create closures is to create another function within one function, and to access local variables of that function through another function;

//through closures can return local variable function box () {var user = ' Lee ';
      return function () {//returns the local variable user of box () via an anonymous function;
    return user;
  };        Console.log (Box () ()); =>lee;

  Call Box () () directly to get the return value of the anonymous function;
  var b = box ();          Console.log (b ()); =>lee;

Another way to invoke an anonymous function; 
Advantages: Local variables can reside in memory, can avoid the use of global variables; 
(global variable pollution causes application unpredictability, each module can invoke a disaster; therefore, private, encapsulated local variables are recommended); 
Disadvantage://through global variables to accumulate var age = 100;
  global variable;              function box () {age++;
  The module level can call global variables to accumulate;
  };                Box ();
  Execute function, accumulate once;           Console.log (age); =>101;
  Output global variables;                Box ();
  Execute function, accumulate once;           Console.log (age); =>102;
Output global variables;
    Additive function cannot be implemented with local variables box () {var age = 100;              age++;
    realize accumulation;
  return age;          Console.log (Box ());
  =>101;          Console.log (Box ()); =>101;

Accumulation cannot be implemented because the function internal variable age is initialized when the function is called the second time;
    The cumulative function of local variables can be realized by closure box () {var age = 100;
      Add in return function () {//anonymous function;
      age++;          return age; 
    and returns the cumulative variable;                };
  The value of the local variable age of the box () function has been modified to the cumulative value at this time;            var b = box ();
  Assign a value to the box () function to the variable;           Console.log (b ()); =>101;
  Call an anonymous function and add it once;           Console.log (b ()); =>102;

The second call anonymous function, accumulate two times; PS: Due to the scope returned in the closure of the local variable resources will not be immediately destroyed recycling, so may occupy more memory, so the excessive use of closures can lead to performance degradation (the closure reference in the "private scope" can be implemented variable destruction)//The mechanism of the scope chain leads to a problem in which any variable obtained by the anonymous function in the loop is the last value. 
The loop contains anonymous functions function box () {var arr = []; 
      for (var i=0 i<5; i++) {//When declaring a variable i=5, the loop stops while the variable in the loop is i==5;
        Arr[i] = function () {//arr[i] only gets an anonymous function function () {} that is not executed;        
      return i;
    };
    };           return arr;
  arr = [Function,function,function,function,function];           var b = box (); =>[function,function,function,function,function];
  Gets the array arr that the function box () returns;       Console.log (b.length); =>5;
  Get the length of the function set array;    for (var i=0 i<b.length; i++) {console.log (box () [i] ()); =>5,5,5,5,5;
  Output the value of each function, which is the last value;
  The result of the above example output is 5, which is the maximum I value obtained after the loop;

Because B[i] calls anonymous functions, anonymous functions do not perform themselves, wait until the call, box () has been executed, I have already become 5;
    The loop contains anonymous functions-1, self-Executing anonymous functions function box () {var arr = [];
        for (var i=0 i<5; i++) {Arr[i] = (function (num) {//arr[i] is the result of the anonymous function execution value 0-4; 
      return num;           }) (i);
    Self-executing and passing the reference; 
  return arr;           var b = box (); =>[0,1,2,3,4];
  At this point B represents the array returned by box (); for (var i = 0; i < B.length;       i++) {Console.log (b[i]); 0 1 2 3 4;
  The value is returned here;
  };

In the example, we allow the anonymous function to execute itself, resulting in an array rather than a function, which ultimately returns to A[i], resulting in the retention of the 0,1,2,3,4 value in the b[0]-b[4];
  The loop contains an anonymous function-2, an anonymous function in the anonymous function; 
    function box () {var arr = [];
          For (Var i=0. i<5; i++) {Arr[i] = (function (num) {return function () {//back functions;      
        return num;
    }) (i);           return arr;
  arr = [Function,function,function,function,function];
  var b = box ();      for (var i = 0; i < b.length i++) {Console.log (B[i] ()); 
  0,1,2,3,4;

};
In 1 and 2, we perform the function by ourselves, and immediately assign the result to arr[i]; Each I, the caller, is passed by value, so the final return is the specified increment I, not the variable i in the box () function;

Three This object

Using this object in closures can cause problems; This object is bound at run time based on the execution environment of a function;
If this is pointing to window on a global scale, if the object is pointing inside the object;
The closure, however, points to window at runtime because the closure does not belong to the object's properties or methods; 
  var user = ' Window ';
  var obj = {
    User: ' Object ',
    getuserfunction:function () {return
      function () {            //closure does not belong to obj, Inside of this point to window;
        return this.user;
      }
  }; Console.log (Obj.getuserfunction () ());      =>window;

  You can force points to an object
  Console.log (Obj.getuserfunction (). Call (obj));  =>object;

  You can also get the object
  getuserfunction:function () {var, = This from the previous scope
    .               Get this from the object's method, at which point it points to the Obj object;
    return function () {return
      That.user
    }
  }
  Console.log (Obj.getuserfunction () ());      =>object;

Four memory leaks

Because IE's JScript objects and Dom objects use different garbage collection methods, closures can cause memory leaks in IE, which means that the elements residing in memory cannot be destroyed;
  function box () {
    var odiv = document.getElementById (' odiv ');//Odiv resides in memory after it has been exhausted;
    Odiv.onclick = function () {
      alert (odiv.innerhtml);          This causes memory leaks with Odiv;
    Odiv = null;                 Remove a reference;
  }
  Box ();
  Because the anonymous function holds a reference to the active object of box (), it causes the number of references that cannot be reduced odiv;
  As long as the anonymous function exists, the number of references to the odiv is at least 1, so the memory it occupies will never be recycled;
  PS: If the dereference is not used, then the browser will not be released until the shutdown;

Five impersonation block-level scopes (defining and calling an anonymous function immediately)

JS does not have a block-level scope of the concept;
  This means that the variable defined in the BLOCK statement (for statement/if statement) is actually created in the containing function rather than in the statement;
    function box (count) {for (var i=0; i<count; i++) {}//box (2); => count=2; i=2 when the loop stops, i=2 at this time;               Console.log (i); =>2;
  I will not fail because it leaves the for block;

  Box (2);                   function box (count) {for (var i=0; i<count; i++) {} var i;
    Even if it is declared again, it will not overwrite the previous value;
  Console.log (i);
Box (2);
In JavaScript, the variable i is defined in the active object of box (), so it can be accessed anywhere within the function, starting with its definition;
The above two examples show that JavaScript has no scope for block-level statements, if () {}/for () {} has no scope;

If there is scope, this range I should be destroyed;

JavaScript does not remind you to declare the same variable multiple times; In this case, it will only ignore subsequent declarations (if it is initialized and assigned, it will be executed);
  Mimics block-level scopes (private scope) (function () {//) is a block-level scope;
  })();

The above code defines and immediately calls an anonymous function, including the function declaration in a pair of parentheses, indicating that it is actually a function expression;
    Use block-level scopes (private scope) to Overwrite function box (count) {() function () {for (var i=0; i<count; i++) {}}) ();                Console.log (i);
  Error, inaccessible; variable i in a private scope, a private scope is destroyed.
Box (2);
With block-level scopes, any variables defined in the anonymous function are destroyed at the end of execution, and (I can only be used in loops and destroyed after use); and the ability to access the variable count in a private scope isBecause this anonymous function is a closure, he is able to access all the variables that contain the scope;
This technique is often used outside the function in the global scope, thus restricting the addition of too many variables and functions to the global scope;
Generally, we should add variables and functions to the global scope as little as possible, and too many global variables and functions can easily lead to naming conflicts;
  Using block-level scopes, each developer can use its own variables without worrying about messing up the global scope;
    (function () {var box = [1,2,3,4];              Console.log (box); =>[1,2,3,4];
  Box out is not recognized;                      })();
  Destroy the variables in the anonymous function;                Console.log (box);
  =>box is not defined; Using block-level scopes in a global scope reduces the memory footprint of closures because there are no references to anonymous functions//As long as the function is finished, the scope chain can be destroyed immediately;

Six private variables

JavaScript does not use the concept of private attributes; all attributes are public;
However, there is a concept of a private variable: A variable defined in any function can be considered a private variable because it cannot be accessed outside the function;
  A private variable includes a function's parameter/local variable and other functions defined within the function;                 function box () {var age = 100;
  Private variable, outside inaccessible;
/and by creating a closure internally, the closure can also access these variables through its own scope chain;
  With this, you can create a common method for accessing a private variable, a privileged method;
    function Box () {//constructor;                 var age = 100;
    Private variable;
      function run () {//private functions;
    Return ' run ... ';
    };
      This.get = function () {//external public privileged method;             return Age+run ();
    Assigning a closure to a variable;
  };
  var box = new box ();

Console.log (Box.get ());              You can access the private variable function person (name) {var user = name by constructing a method pass parameter;
    This sentence can actually be omitted;
    This.getuser = function () {return user;
    };
    This.setuser = function (name) {user = name;
  } var p = new Person (' Lee ');            Console.log (P.getuser ());
  =>lee;
  Console.log (P.setuser (' Jack '));            Console.log (P.getuser ());
  =>jack; However, the disadvantage of the constructor pattern is that theEach instance creates the same set of new methods, and the use of static private variables to implement privileged methods can avoid this problem; 

seven static private variables

By defining a private variable or function in a block-level scope (private scope), you can also create an external public privileged method;
    (function () {//create private scope;               var age = 100;
    static private variables;
    function run () {return ' run ... ';
    };             Box = function () {};
    Use function expressions to define constructors;
      Box.prototype.go = function () {//Public (privileged) method; defined on a prototype;
    return Age+run ();
  };
  })();
  var box = new box ();             Console.log (Box.go ());
100 Running ...; The above object declares that the box = function () {} Instead of Functiong box () {} is used, and that when the box is declared it is not using the var keyword//Cause: Initialize the undeclared variable and always create a global variable;
Box becomes a global variable that can be accessed outside a private scope;
  Because if you define a constructor with a function declaration, you become a private function and cannot be accessed globally, so you use a functional definition of the constructor method;
    (function () {var user = "";
      person = function (value) {//the person defined here is a global variable;              user = value;
    The constructor here has permission to access the private variable name;
    };
    Person.prototype.getUser = function () {return user;
    };
    Person.prototype.setUser = function (value) {user = value;
  }
  })();
  var person = new person ();
  Person.setuser (' Lee '); Console.log (Person.getuser ());         =>lee;
The use of prototype causes the method to be shared, and user becomes a static property; Static properties: That is, the attributes shared in different objects;?

Eight module mode

In short, you can use module mode if you have to create an object and initialize it with some data while exposing some ways to access the private data;
All of the previous uses are constructors to create private variables and privileged methods;
  Then the object literal method is created by module mode.
    var box = {//literal object, also Singleton object: object with only one instance;
    AGE:100,//This is a public property that will be changed into private;
    Run:function () {return ' run ... ';
  };

};
    Module mode privatization variables and functions: var box = function () {var age = 100;
    function run () {return ' run ... ';
      return {///returns a literal object as the value of the function;
        The Go:function () {///returned object literal contains only properties and methods that can be exposed;          return Age+run ();
      Because this object is defined within an anonymous function, its public method has access to private variables and functions;                      }                  
    };
  Essentially, this object literal defines a single instance of the public interface;
}(); 

This pattern is useful when you need to initialize some of the individual cases while maintaining their private variables;
    The example that returns the object directly above can also be written as follows: var box = function () {var age = 100;
    function run () {return ' run ... ';
      var obj = {//create literal object;
      Go:function () {return age+run ();
    }
    };                  return obj;
  Returns the object that was just created;

}(); LiteralThe object declaration of quantity, in fact, can be regarded as a single case pattern in design pattern;

The so-called single case mode, is always keep the object of only one instance;
  Enhanced module mode: Suitable for returning custom objects, i.e. constructors;
  function Desk () {};
    var box = function () {var age = 100;
    function run () {return ' run ... ';
    };
    var desk = new Desk ();
    Desk.go = function () {return age+run ();
    };
  return desk;
  }();              Console.log (Box.go ()); =>100 in operation;

Ix. Summary

In JavaScript programming, function expressions are a very useful technique; You can use function expressions to implement dynamic programming without having to name the function.

1. Expression of function

A function expression differs from a function declaration, a function declaration requires a name, but a function expression is not required;
A function expression without a name is called an anonymous function; 2. Closures
When other functions are defined inside a function, a closure is created. The closure has access to all variables within the containing function; the principle is as follows:
In the background execution environment, the scope chain of the closure contains its own scope, the scope of the containing function and the global scope;
Typically, the scope of a function and all its variables are destroyed after the function is executed;
However, when a function returns a closure, the scope of the function will remain in memory until the closure does not exist; 3. Block-level scopes
Using closures, you can mimic block-level scopes in JavaScript (the notion that JavaScript itself does not have block-level scopes);
Create and call a function immediately so that you can execute the code in it without leaving a reference to the function in memory;
The result is that all the variables inside the function are destroyed immediately--unless some of the variables are assigned to a variable in the scope (that is, an external scope); 4. Private variables
Closures can also be used to create private variables in objects, with the following points:
Even though JavaScript does not have the concept of a true private object attribute, a closure can be used to implement the public method, and a public method can access the variables defined in the scope;
You can use a constructor pattern, a prototype pattern, to implement a privileged method of a custom type, or you can use a module pattern to implement the privileged method of a single instance;

Related Article

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.