JavaScript in-depth understanding of JS closures

Source: Internet
Author: User
Tags closure variable scope

The scope of a variable

To understand closures, you must first understand the special variable scope of JavaScript.

The scope of a variable is nothing more than two kinds: global variables and local variables.

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


JS Code

var n=999;

Function F1 () {
alert (n);
}

F1 (); 999

On the other hand, a local variable inside a function cannot be read naturally outside the function.

JS Code

Function F1 () {
var n=999;
}

alert (n); Error

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

JS Code

Function F1 () {
n=999;
}

F1 ();

alert (n); 999

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

Second, how to read the local variables from the outside?

For a variety of reasons, we sometimes need to get local variables within the function. However, as already mentioned, under normal circumstances, this can not be done, only through the workaround to achieve.

That is, in the inside of the function, define a function.

JS Code

Function F1 () {

n=999;

function F2 () {
alert (n); 999
}

}

In the above code, the function F2 is included inside the function F1, and all local variables inside the F1 are visible to the F2. But the opposite is not possible, F2 internal variables, the F1 is not visible. This is the "chain-scoped" structure (chain scope) that is unique to the JavaScript language.

The child object looks up the variables for all the parent objects first-level. Therefore, all the variables of the parent object are visible to the child object, and vice versa.

Since F2 can read the local variables in the F1, we can not read its internal variables outside the F1 as long as the F2 is the return value!


JS Code

Function F1 () {

n=999;

function F2 () {
alert (n);
}

return F2;

}

var result=f1 ();

Result (); 999

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

Three, the concept of closure

The F2 function in the previous section of the code is the closure.

The definition of "closure" (closure) in various professional literature is very abstract and difficult to read. My understanding is that closures 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.

--------------------------------------------------------------------------------------------------------b

Iv. use of closures

Closures can be used in many places. Its maximum usefulness is two, one of the previously mentioned variables that can read the inside of a function, and the other is to keep the values of these variables in memory at all times.

How to understand this sentence? Take a look at the following code.


JS Code

Function F1 () {

var n=999;

Nadd=function () {n+=1}

function F2 () {
alert (n);
}

return F2;

}

var result=f1 ();

Result (); 999

Nadd ();

Result (); 1000

In this code, result is actually the closure F2 function. It runs altogether two times, the first value is 999, the second value is 1000. This proves that the local variable n in the function F1 is kept in memory and is not automatically cleared after the F1 call.

Why is that? The reason is that F1 is the parent function of F2, and F2 is assigned to a global variable, which causes F2 to always be in memory, and F2 's presence depends on F1, so F1 is always in memory and will not be reclaimed by the garbage collection mechanism (garbage collection) after the call ends.

Another notable part of this code is the line "nadd=function () {n+=1}", which first did not use the var keyword in front of Nadd, so Nadd is a global variable, not a local variable. Second, the value of Nadd is an anonymous function (anonymous functions), and this

The anonymous function itself is also a closure, so nadd is equivalent to a setter that can manipulate local variables inside the function outside of the function.

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

V. Note points for using closures

1) Because the closure will make the variables in the function are stored in memory, memory consumption is very large, so can not abuse closures, otherwise it will cause the performance of the Web page, in IE may cause memory leaks. The workaround is to remove all unused local variables before exiting the function.

2) The closure changes the value of the inner variable of the parent function outside the parent function. So, if you use the parent function as an object, take the closure as its common method, and take the internal variable as its private property (private value), then be careful not to casually

Change the value of the inner variable of the parent function.

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

Liu, study questions

If you can understand the running result of the code below, you should understand the operation mechanism of the closure.

JS Code
var name = "the window";
var object = {
Name: "My Object",
Getnamefunc:function () {
return function () {
return this.name;
};
}
};
Alert (Object.getnamefunc () ()); The Window

--------------------------------------------------------------------------------------------------------
JavaScript Closures Example

function Outerfun ()
{
var a=0;
function Innerfun ()
{
a++;
alert (a);
}
}
Innerfun ()

The above code is wrong. The scope of Innerfun () is inside Outerfun () and it is wrong to call it outside the Outerfun ().

Change to the following, i.e. closures:

JS Code

function Outerfun ()
{
var a=0;
function Innerfun ()
{
a++;
alert (a);
}
return innerfun; Watch this.
}
var obj=outerfun ();
obj (); Result is 1
obj (); Result is 2
var obj2=outerfun ();
Obj2 (); Result is 1
Obj2 (); Result is 2

What is a closure package:

When an intrinsic function is referenced outside the scope that defines it, the inner function's closure is created, and if the intrinsic function references a variable that is located outside the function, when the external function is called, the variables are not freed in memory because the closures require them.

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

Let's look at one more example

JS Code

function Outerfun ()
{
var a = 0;
alert (a);
}
var a=4;
Outerfun ();
alert (a);

The result is 0,4. Because the VAR keyword is used inside a function to maintain the scope of a within outfun ().

Then look at the following code:

JS Code

function Outerfun ()
{
No Var
A = 0;
alert (a);
}
var a=4;
Outerfun ();
alert (a);
The result is 0, 0 is really strange, why?

A scope chain is a term that describes a path that can be used to determine the value of a variable. When a=0 is executed, the assignment is linked to Var a=4 along the scope, because the VAR keyword is not employed; and change its value.

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

If you do not understand JavaScript closures, then please see the following reproduced article: (Reprint: http://www.felixwoo.com/archives/247)

One, what is closures?

The official explanation is that closures are an expression (usually a function) that has many variables and environments that bind them, and so these variables are also part of the expression.
It is believed that very few people can read this sentence directly because he describes it as too academic. In fact, the phrase is:all the function in JavaScript is a closed packet . In general, however, the nested function produces a more powerful closure, which is what we call "closures" most of the time. Look at the following code:




return b;
}
var C = A ();
C ();

There are two features of this code:

1. function b is nested inside function A;

2, function a returns function B.

Referential relationships

So after executing var c=a (), the variable C actually points to function B, and then C () pops up a window showing the value of I (first 1). This code actually creates a closure, why? Because the variable C outside of function A refers to function B in function A, that is:

  When function A's intrinsic function B is referenced by a variable outside of function A, a closure is created.

Let's talk a little more thoroughly. A "closure" is a method function that defines another function as the target object in the body of the constructor, and the method function of the object in turn refers to the temporary variable in the outer function body. This makes it possible to indirectly maintain the value of temporary variables used by the original constructor body as long as the target object retains its method throughout its lifetime. Although the initial constructor call has ended, the name of the temporary variable disappears, but the value of the variable is always referenced within the method of the target object, and the value can only be accessed through this method. Even if the same constructor is called again, but only new objects and methods are generated, the new temporary variable only corresponds to the new value, and the last time the call was separate.

What is the role of closures?

In short, the function of a closure is that after a executes and returns, the closure makes the garbage collection mechanism of the JavaScript GC does not reclaim the resources used by a, because the execution of the internal function B of a requires a dependency on the variables in a. This is a very straightforward description of the effect of closures, unprofessional and not rigorous, but the general meaning is that, understanding closures need a gradual process.

In the above example, because the existence of a closure causes function A to return, I in a always exists, so that every time C (), I is added 1 after the alert out of the value of I.

So let's imagine another situation where a returns a function B, which is completely different. Since a executes, B is not returned to the outside world of a, only a is referenced by a, and at this point a will only be referenced by B, so functions A and B are referenced by each other but are not disturbed by the outside world (referenced by the outside world), functions A and B will be collected by GC. (The garbage collection mechanism for JavaScript will be described in more detail later)

Third, the microcosm within the closures

To gain a deeper understanding of the relationship between closures and function A and nested function B, we need to introduce several other concepts: the function's execution environment (excution context), the active object (call object), scope (scope), scope chain (scope chain). Take function A from definition to execution as an example to illustrate these concepts.

    1. When defining function A, the JS interpreter sets the scope chain of function A to the "Environment" where A is located, and if A is a global function, the scope Only the Window object is in the chain.
    2. When the function A is executed , a is entered into the appropriate execution Environment (excution context).
    3. During the creation of the execution environment, a scope property, the scope of a, is first added for a, and the value is the scope chain in step 1th. That is, the scope chain of the a.scope=a.
    4. The execution environment then creates an active object (Call object). The active object is also an object with properties, but it does not have a prototype and is not directly accessible through JavaScript code. After the active object is created, add the active object to the top of the scope chain of a. At this point A's scope chain contains two objects: A's active object and the Window object.
    5. The next step is to add a arguments property on the active object, which holds the arguments passed when the function A is called.
    6. Finally, the reference of all function A's parameters and internal function B is added to the active object of a. In this step, the definition of function B is completed, so as in the 3rd step, the scope chain of function B is set to the environment defined by B, which is the scope of a.

This completes the entire function A from definition to execution. At this point a returns a reference to function B to C, and the scope chain of function B contains a reference to the active object of function A, which means that B can access all the variables and functions defined in a. Function B is referenced by C and function B relies on function A, so function A is not recycled by GC after it returns.

When function B executes, it will be the same as the above steps. Therefore, the scope chain of execution B contains 3 objects: The active object of B, the active object of a, and the Window object, as shown in:

, when a variable is accessed in function B, the search order is:

    1. Searches for the active object itself first, if it exists, returns if there is no active object that will continue to search for function A, and then finds it until it is found.
    2. If the prototype prototype object exists in function B, it finds its own prototype object after it finds its own active object, and then continues to look for it. This is the variable lookup mechanism in JavaScript.
    3. Returns undefined if none of the entire scope chain is found.

Summary, two important words are mentioned in this paragraph: definition and execution of functions. It is mentioned in the article that the scope of the function is determined when the function is defined, not when it is executed (see steps 1 and 3). Use a piece of code to illustrate the problem:


var g = function () {return x;}
return g;
}
var h = f (1);
Alert (H ());

The variable h in this code points to the anonymous function (returned by G) in F.

    • Assuming that the scope of the function h is determined by the execution alert (h ()), then the scope chain of H is: H's active object->alert the active object->window object.
    • Assuming that the scope of the function h is defined at the time of definition, the anonymous function pointed to by H has been scoped at the time of definition. Then, at execution time, the scope chain of H is: H's active object->f the active object->window object.

If the first hypothesis is true, the output value is undefined; if the second hypothesis is true, the output value is 1.

The result of the operation proves that the 2nd hypothesis is correct, stating that the scope of the function is indeed determined when the function is defined.

Four, closure of the application scenario
Security of variables within the protection function. For example, in the first example, function A can only be accessed by function B, and cannot be accessed by other means, thus protecting the security of I.

    1. Maintains a variable in memory. Still as in the previous example, because of the closure, the function A in the I has been in memory, so each execution C (), will give I self plus 1.
    2. JS private properties and private methods (cannot be accessed externally) through the secure implementation of the protection variables
      Private properties and methods cannot be accessed outside of constructor

      function Constructor (...) {
      var = this;
      var membername = value;
      function MemberName (...) {...}
      }

The above 3 points are the most basic application scenarios for closures, and many of the classic cases originate from this.

V. JavaScript's garbage collection mechanism

In JavaScript, if an object is no longer referenced, the object is recycled by the GC. If two objects are referenced by each other and are no longer referenced by the 3rd, then the two mutually referenced objects are also recycled. Because function A is referenced by B and B is referenced by a c outside of a, this is why function A is not recycled after execution.

Vi. Conclusion

Understanding JavaScript closures is the way to advanced JS programmers, understanding their interpretation and operational mechanisms to write more secure and elegant code.

The scope of a variable

To understand closures, you must first understand the special variable scope of JavaScript.

The scope of a variable is nothing more than two kinds: global variables and local variables.

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


JS Code

var n=999;

Function F1 () {
alert (n);
}

F1 (); 999

On the other hand, a local variable inside a function cannot be read naturally outside the function.

JS Code

Function F1 () {
var n=999;
}

alert (n); Error

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

JS Code

Function F1 () {
n=999;
}

F1 ();

alert (n); 999

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

Second, how to read the local variables from the outside?

For a variety of reasons, we sometimes need to get local variables within the function. However, as already mentioned, under normal circumstances, this can not be done, only through the workaround to achieve.

That is, in the inside of the function, define a function.

JS Code

Function F1 () {

n=999;

function F2 () {
alert (n); 999
}

}

In the above code, the function F2 is included inside the function F1, and all local variables inside the F1 are visible to the F2. But the opposite is not possible, F2 internal variables, the F1 is not visible. This is the "chain-scoped" structure (chain scope) that is unique to the JavaScript language.

The child object looks up the variables for all the parent objects first-level. Therefore, all the variables of the parent object are visible to the child object, and vice versa.

Since F2 can read the local variables in the F1, we can not read its internal variables outside the F1 as long as the F2 is the return value!


JS Code

Function F1 () {

n=999;

function F2 () {
alert (n);
}

return F2;

}

var result=f1 ();

Result (); 999

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

Three, the concept of closure

The F2 function in the previous section of the code is the closure.

The definition of "closure" (closure) in various professional literature is very abstract and difficult to read. My understanding is that closures 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.

--------------------------------------------------------------------------------------------------------b

Iv. use of closures

Closures can be used in many places. Its maximum usefulness is two, one of the previously mentioned variables that can read the inside of a function, and the other is to keep the values of these variables in memory at all times.

How to understand this sentence? Take a look at the following code.


JS Code

Function F1 () {

var n=999;

Nadd=function () {n+=1}

function F2 () {
alert (n);
}

return F2;

}

var result=f1 ();

Result (); 999

Nadd ();

Result (); 1000

In this code, result is actually the closure F2 function. It runs altogether two times, the first value is 999, the second value is 1000. This proves that the local variable n in the function F1 is kept in memory and is not automatically cleared after the F1 call.

Why is that? The reason is that F1 is the parent function of F2, and F2 is assigned to a global variable, which causes F2 to always be in memory, and F2 's presence depends on F1, so F1 is always in memory and will not be reclaimed by the garbage collection mechanism (garbage collection) after the call ends.

Another notable part of this code is the line "nadd=function () {n+=1}", which first did not use the var keyword in front of Nadd, so Nadd is a global variable, not a local variable. Second, the value of Nadd is an anonymous function (anonymous functions), and this

The anonymous function itself is also a closure, so nadd is equivalent to a setter that can manipulate local variables inside the function outside of the function.

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

V. Note points for using closures

1) Because the closure will make the variables in the function are stored in memory, memory consumption is very large, so can not abuse closures, otherwise it will cause the performance of the Web page, in IE may cause memory leaks. The workaround is to remove all unused local variables before exiting the function.

2) The closure changes the value of the inner variable of the parent function outside the parent function. So, if you use the parent function as an object, take the closure as its common method, and take the internal variable as its private property (private value), then be careful not to casually

Change the value of the inner variable of the parent function.

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

Liu, study questions

If you can understand the running result of the code below, you should understand the operation mechanism of the closure.

JS Code
var name = "the window";
var object = {
Name: "My Object",
Getnamefunc:function () {
return function () {
return this.name;
};
}
};
Alert (Object.getnamefunc () ()); The Window

--------------------------------------------------------------------------------------------------------
JavaScript Closures Example

function Outerfun ()
{
var a=0;
function Innerfun ()
{
a++;
alert (a);
}
}
Innerfun ()

The above code is wrong. The scope of Innerfun () is inside Outerfun () and it is wrong to call it outside the Outerfun ().

Change to the following, i.e. closures:

JS Code

function Outerfun ()
{
var a=0;
function Innerfun ()
{
a++;
alert (a);
}
return innerfun; Watch this.
}
var obj=outerfun ();
obj (); Result is 1
obj (); Result is 2
var obj2=outerfun ();
Obj2 (); Result is 1
Obj2 (); Result is 2

What is a closure package:

When an intrinsic function is referenced outside the scope that defines it, the inner function's closure is created, and if the intrinsic function references a variable that is located outside the function, when the external function is called, the variables are not freed in memory because the closures require them.

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

Let's look at one more example

JS Code

function Outerfun ()
{
var a = 0;
alert (a);
}
var a=4;
Outerfun ();
alert (a);

The result is 0,4. Because the VAR keyword is used inside a function to maintain the scope of a within outfun ().

Then look at the following code:

JS Code

function Outerfun ()
{
No Var
A = 0;
alert (a);
}
var a=4;
Outerfun ();
alert (a);
The result is 0, 0 is really strange, why?

A scope chain is a term that describes a path that can be used to determine the value of a variable. When a=0 is executed, the assignment is linked to Var a=4 along the scope, because the VAR keyword is not employed; and change its value.

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

If you do not understand JavaScript closures, then please see the following reproduced article: (Reprint: http://www.felixwoo.com/archives/247)

One, what is closures?

The official explanation is that closures are an expression (usually a function) that has many variables and environments that bind them, and so these variables are also part of the expression.
It is believed that very few people can read this sentence directly because he describes it as too academic. In fact, the phrase is:all the function in JavaScript is a closed packet . In general, however, the nested function produces a more powerful closure, which is what we call "closures" most of the time. Look at the following code:




return b;
}
var C = A ();
C ();

There are two features of this code:

1. function b is nested inside function A;

2, function a returns function B.

Referential relationships

So after executing var c=a (), the variable C actually points to function B, and then C () pops up a window showing the value of I (first 1). This code actually creates a closure, why? Because the variable C outside of function A refers to function B in function A, that is:

  When function A's intrinsic function B is referenced by a variable outside of function A, a closure is created.

Let's talk a little more thoroughly. A "closure" is a method function that defines another function as the target object in the body of the constructor, and the method function of the object in turn refers to the temporary variable in the outer function body. This makes it possible to indirectly maintain the value of temporary variables used by the original constructor body as long as the target object retains its method throughout its lifetime. Although the initial constructor call has ended, the name of the temporary variable disappears, but the value of the variable is always referenced within the method of the target object, and the value can only be accessed through this method. Even if the same constructor is called again, but only new objects and methods are generated, the new temporary variable only corresponds to the new value, and the last time the call was separate.

What is the role of closures?

In short, the function of a closure is that after a executes and returns, the closure makes the garbage collection mechanism of the JavaScript GC does not reclaim the resources used by a, because the execution of the internal function B of a requires a dependency on the variables in a. This is a very straightforward description of the effect of closures, unprofessional and not rigorous, but the general meaning is that, understanding closures need a gradual process.

In the above example, because the existence of a closure causes function A to return, I in a always exists, so that every time C (), I is added 1 after the alert out of the value of I.

So let's imagine another situation where a returns a function B, which is completely different. Since a executes, B is not returned to the outside world of a, only a is referenced by a, and at this point a will only be referenced by B, so functions A and B are referenced by each other but are not disturbed by the outside world (referenced by the outside world), functions A and B will be collected by GC. (The garbage collection mechanism for JavaScript will be described in more detail later)

Third, the microcosm within the closures

To gain a deeper understanding of the relationship between closures and function A and nested function B, we need to introduce several other concepts: the function's execution environment (excution context), the active object (call object), scope (scope), scope chain (scope chain). Take function A from definition to execution as an example to illustrate these concepts.

    1. When defining function A, the JS interpreter sets the scope chain of function A to the "Environment" where A is located, and if A is a global function, the scope Only the Window object is in the chain.
    2. When the function A is executed , a is entered into the appropriate execution Environment (excution context).
    3. During the creation of the execution environment, a scope property, the scope of a, is first added for a, and the value is the scope chain in step 1th. That is, the scope chain of the a.scope=a.
    4. The execution environment then creates an active object (Call object). The active object is also an object with properties, but it does not have a prototype and is not directly accessible through JavaScript code. After the active object is created, add the active object to the top of the scope chain of a. At this point A's scope chain contains two objects: A's active object and the Window object.
    5. The next step is to add a arguments property on the active object, which holds the arguments passed when the function A is called.
    6. Finally, the reference of all function A's parameters and internal function B is added to the active object of a. In this step, the definition of function B is completed, so as in the 3rd step, the scope chain of function B is set to the environment defined by B, which is the scope of a.

This completes the entire function A from definition to execution. At this point a returns a reference to function B to C, and the scope chain of function B contains a reference to the active object of function A, which means that B can access all the variables and functions defined in a. Function B is referenced by C and function B relies on function A, so function A is not recycled by GC after it returns.

When function B executes, it will be the same as the above steps. Therefore, the scope chain of execution B contains 3 objects: The active object of B, the active object of a, and the Window object, as shown in:

, when a variable is accessed in function B, the search order is:

    1. Searches for the active object itself first, if it exists, returns if there is no active object that will continue to search for function A, and then finds it until it is found.
    2. If the prototype prototype object exists in function B, it finds its own prototype object after it finds its own active object, and then continues to look for it. This is the variable lookup mechanism in JavaScript.
    3. Returns undefined if none of the entire scope chain is found.

Summary, two important words are mentioned in this paragraph: definition and execution of functions. It is mentioned in the article that the scope of the function is determined when the function is defined, not when it is executed (see steps 1 and 3). Use a piece of code to illustrate the problem:


var g = function () {return x;}
return g;
}
var h = f (1);
Alert (H ());

The variable h in this code points to the anonymous function (returned by G) in F.

    • Assuming that the scope of the function h is determined by the execution alert (h ()), then the scope chain of H is: H's active object->alert the active object->window object.
    • Assuming that the scope of the function h is defined at the time of definition, the anonymous function pointed to by H has been scoped at the time of definition. Then, at execution time, the scope chain of H is: H's active object->f the active object->window object.

If the first hypothesis is true, the output value is undefined; if the second hypothesis is true, the output value is 1.

The result of the operation proves that the 2nd hypothesis is correct, stating that the scope of the function is indeed determined when the function is defined.

Four, closure of the application scenario
Security of variables within the protection function. For example, in the first example, function A can only be accessed by function B, and cannot be accessed by other means, thus protecting the security of I.

    1. Maintains a variable in memory. Still as in the previous example, because of the closure, the function A in the I has been in memory, so each execution C (), will give I self plus 1.
    2. JS private properties and private methods (cannot be accessed externally) through the secure implementation of the protection variables
      Private properties and methods cannot be accessed outside of constructor

      function Constructor (...) {
      var = this;
      var membername = value;
      function MemberName (...) {...}
      }

The above 3 points are the most basic application scenarios for closures, and many of the classic cases originate from this.

V. JavaScript's garbage collection mechanism

In JavaScript, if an object is no longer referenced, the object is recycled by the GC. If two objects are referenced by each other and are no longer referenced by the 3rd, then the two mutually referenced objects are also recycled. Because function A is referenced by B and B is referenced by a c outside of a, this is why function A is not recycled after execution.

Vi. Conclusion

Understanding JavaScript closures is the way to advanced JS programmers, understanding their interpretation and operational mechanisms to write more secure and elegant code.

JavaScript in-depth understanding of JS 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.