The closure in JS (closure)

Source: Internet
Author: User

The closure in JS (closure)

Closures (closure) are a difficult and unique feature of the JavaScript language, and many advanced applications rely on closures.
Here is my study note, which should be useful for JavaScript beginners.

I. What is closures

In JS, variables outside the function can be read inside the function

function outer () {     var localval =;      return Localval;} Outer ();//30

However, a local variable inside a function cannot be read naturally outside the function

function outer () {     var localval =; }alert (localval);//error

Here's a place to be aware that when declaring variables inside a function, be sure to use the var command. If not, a global variable is actually declared.

function outer () {     localval =;      return Localval;} Outer ();
alert (localval);//30

The above statement, is the scope of the JS variable knowledge, it includes global variables and local variables.

The special point of the JavaScript language is that the global variables can be read directly inside the function.

function outer () {     var localval =;
function Inner () {          alert (localval);     }
     return inner;} var func = outer (); func ();//30

We see in the above code, the outer function also defines a function Inner,outer function return value is inner function, inner function localval alert out.

We can see the features of the above code: function nesting functions, intrinsic functions can refer to parameters and variables of external functions, parameters and variables are not reclaimed by garbage collection mechanism.

The inner function in the code is the closure. Simply put, closures (closure) are functions that can read other functions ' internal variables.

Because in the JavaScript language, only sub-functions inside the function can read local variables, it is possible to simply interpret the closure as "a function defined inside a function". So, in essence, a closure is a bridge that connects the inside of the function to the outside of the function.

In the above code, the function inner is contained inside the function outer, and all local variables inside the outer are visible to the inner. But the local variables inside the inner are not visible to oute. This is a "chain-scoped" structure specific to the JavaScript language (chain scope), where child objects look up the variables of all parent objects one level at a level. Therefore, all the variables of the parent object are visible to the child object, and vice versa.

Complement the function definitions in--JS

JS defines a function, the most common is the function declaration and function expression

The function declaration in JS refers to the following form:

function functionname () {    }

function expressions are like expressions that declare a function:

var function (){  }

We can use a function expression to create a function and execute it immediately, such as:

(function() {  var a, B    //  Local Variables  //  ...      and The Code}) ()

() (); A nameless function is placed in the first parenthesis.

The difference : The parser of JS does not treat function declaration and function expression equally. For a function declaration, the JS parser will read first, ensuring that the declaration has been parsed before all code executes, and that the function expression, like a variable of other primitive types, will be parsed only when executed to a certain sentence, so in practice, they will be different. When you define a function using the form of a function declaration, you can write the call statement before the function declaration, and the latter, in doing so, will error.

Two. Application of closures

Benefits of using closures:

-Want a variable to be stationed in memory for a long time;

-Avoid the pollution of global variables;

-The existence of private members

1. Modular Code

Using self-executing anonymous functions to simulate block-level scopes

(function() {        //  This is a block-level scope }) ();

This method is often used outside the function in the global scope, restricting the addition of too many variables and functions to the global scope to affect the global scope. It is also possible to reduce the use of internal storage such as closures, since anonymous functions do not have a variable point, and the scope chain can be destroyed immediately after execution.

Example:

var test = (function() {    var a= 1;     return function () {        a+ +;        alert (a);    }}) (); test (); // 2test (); // 3

To achieve a self-added, not polluting the overall.

2. Loop closure

Loop to each Li register for a click event, click the alert sequence number. The code is as follows:

var aLi = document.getelementbyclassname ("test"); function Showallnum (aLi) {    forvar i =0,len = ali.length; i<len;i++ ) {              function() {            alert (i); // All is ali.length!         }    }}

Clicking will always pop up the same value ali.length instead of 123. The loop has ended before the click, and the I value is ali.length.

using closures, an anonymous function is built, each I exists in memory , and the onclick function is used to fetch the I value of the external anonymous function. The code is as follows:

var aLi = document.getelementbyclassname ("test"); function Showallnum (aLi) {    forvar i =0,len = ali.length; i<len;i++ ) {        (  function(i) {            function() {            alert (i);        }        }) (i);    }}

Or:

function Showallnum (aLi) {    forvar i =0,len = ali.length; i<len;i++ ) {            = (  function(i) {                returnfunction() {                    alert (i);                }            }) (i);    }}
3. Encapsulation

External cannot directly get the variables within the function, can be obtained by exposing the method

varinfo = (function(){    var_userid = 23492; var_typeid = ' item '; functiongetUserId () {alert (_userid); }    functionGetTypeId () {alert (_typeid); }}); Info.getuserid ();//23492Info.gettypeid ();//ItemInfo._userid//undefinedInfo._typeid//undefined

But this approach will allow us to create this method every time we create a new object. Use prototypes to create a method that avoids creating different methods for each instance. Do not delve into it here (General constructor plus attributes, prototype plus method).

4. About this object

The This object is bound by the execution environment of the function at run time (global in the anonymous function) (this: the element that currently occurs), and sometimes it is somewhat less obvious in some cases of closures.

Code Listing 1:

var name = "the window"; var obj = {    "the object",    function() {        return function () {            returnthis. Name;}}    } Alert (obj. Getnamefunc ())//theWindow

Code Listing 2:

 var  name= "The window" var  obj = {name:  "The object"  function   { var  _this = this  ;  return  function   () { return   _this.name; }}}alert (Object.getnamefunc ());  // the object  

JavaScript is a dynamic (or dynamic type) language, and the This keyword is executed to determine who it is. So this always points to the caller, that is, a reference to the ' Call object ' person. The first part passes code: After executing the code object.getnamefunc (), it returns a new function, noting that the function object is not one with object and can be understood as a global function; it is not a property or method of object, at which time the caller is a window, So the output is the Window.

The second part returns when the function Object.getnamefunc () is executed:

function () {         return  _this.name;}

At this time the that=this. And this points to object, so that's point to object. He is a reference to object, so output my object.

Summary: About JS in this, remember who called, this is pointing to who; to access the closure of this, define a variable cache. Generally like var _this = this.

5. Closure of memory leaks in IE

Before IE9, JScript objects and COM objects use different garbage collection routines, then closures can cause problems.

Create a closure, and then the closure has a circular reference created, then the element cannot be destroyed. The common thing is that the DOM gets the attributes (or methods) of the elements or arrays to invoke its own properties. For example:

function handler () {    var ele = document.getElementById ("ele");     function () {        alert (ele.id);    }}

The closure refers to the entire active object that contains the function, that is, the closure does not directly reference Ele, and the active object still holds a reference to it, so setting null can break the saved reference and free up memory. The code is as follows:

function handler () {    var ele = document.getElementById ("ele");     var id = ele.id;     function () {        alert (ID);    }     NULL ;}

Of course there are other ways to recommend this method.

Three. The principle of closure

When a function is called for the first time, an execution environment (execution context) and the corresponding scope chain are created, and the scope chain is assigned to a special internal property (that is, [[Scope]]). Then, use the values of this, Arguncmts, and other named parameters to initialize the function's active object (Activation object). However, in the scope chain, the active object of the outer function is always second, and the outer function of the external functions of the active object is in the third position ... To the global execution environment as the end of the scope chain.

During function execution, to read and write the value of a variable, you need to find the variable in the scope chain. Take a look at the following example:

function
    If
       return -1;     Else if
       return 1;     Else  {       return 0;    }} var result = Compare (5, 10);

The above code first defines the compare () function and then calls it in the global scope. When compare () is called for the first time, a live object containing this, arguments, Valuel, and value2 is created. The variable objects for the global execution environment (including this, result, and compare) are second in the scope chain of the Compare () execution environment. The diagram shows the scope chain when the compare () function that contains the above relationship executes.

Each execution environment in the background has an object that represents a variable-the variable object. A variable object for a global environment always exists, whereas a variable object of a local environment such as the Compare () function exists only during the execution of a function. When you create the Compare () function, a scope chain is created that contains the global child-changing object, which is stored in the internal [Scope] property. When the Compare () function is called, an execution environment is created for the function and then the scope chain of the execution environment is built from the object in the [Scope] property of the copy function. Thereafter, another active object (used here as a variable object) is created and pushed into the front end of the execution environment scope chain. For the execution environment of the Compare () function in this example, its scope chain contains two variable objects: The local active object and the global variable object. Obviously, a scope chain is essentially a pointer to a variable object list, which only references but does not actually contain variable objects.

Whenever a variable is accessed in a function, a variable with the corresponding name is searched from the scope chain. In general, when the function is finished, the local active object is destroyed, and only the global scope (the variable object of the global execution environment) is saved in memory. However, closures are different.

functioncreatecomparisonfunction (PropertyName) {return function(Object1, object2) {varValuel =Objectl[propertyname];varvalue2 =Object2[propertyname];if(Valuel <value2) { return-1; } Else if(Valuel >value2) { return1; } Else {return0;}};}

A function defined inside another function adds the active object containing the function (that is, the outer function) to its scope chain. Therefore, in the scope chain of the anonymous function defined inside the createcomparisonfunction (), it will actually contain the active object of the external function createcomparisonfunction (). The diagram shows the scope chain that contains functions and internal anonymous functions when the following code executes.

var compare = Createcomparisonfunction ("name"); var result = Compare ({name: "Nicholas"}, {Naine:bgreg "});

After the anonymous function is returned from createcomparisonfunction () 冋, its scope chain is initialized to the active and global variable objects that contain the Createcomparisonfunction () function. In this way, the anonymous function can access all the variables defined in Createcomparisonfunction (). More importantly, the createcoir.parisonfunction () function will not be destroyed after execution, because the scope chain of the anonymous function is still referencing the active object. In other words, when the createcomparisonfunction () function returns, the scope chain of its execution environment is destroyed, but its active objects remain in memory until the anonymous function is destroyed, createcomparisonfunction () Object will be destroyed, for example:

var comparenames = createcomparisonfunction ("name"); // calling Functions var result = Comparenames ({name: "Nicholas"), {name: "Greg" }); // dereference an anonymous function (to free memory) null;

First, the created comparison function is saved in the variable coinparenames. By setting comparenames equal to NULL to dismiss the function's reference, it is tantamount to notifying the garbage collection routine to clear it. As the scope chain of anonymous functions is destroyed, other scopes (except the R global scope) can be safely destroyed. The diagram shows the relationship between the scope chains generated during the call to Conparenameso.

--------------------------------------------------------------------------------------------------------------- ------------------------

Closures are everywhere, and it's very important to know.

Finish

Reproduced must be reproduced in the words, the original author and the original post address.

The closure in JS (closure)

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.