JavaScript deep understanding of JS closure _javascript Skills _ Script Home
closures (closure) are a difficult and unique feature of the JavaScript language, and many advanced applications rely on closure implementations.
scope of a variable
To understand closures, you must first understand JavaScript's special variable scope.
The scope of a variable is nothing more than two kinds: global and local variables.
The special point of the JavaScript language is that the global variable can be read directly from within the function.
JS Code
var n=999;
Function F1 () {
alert (n);
}
F1 (); 999
On the other hand, local variables within a function cannot naturally be read 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, you must use the var command. If not, you actually declare a global variable.
JS Code
Function F1 () {
n=999;
}
F1 ();
alert (n); 999
--------------------------------------------------------------------------------------------------------
second, how to read local variables from the outside.
For a variety of reasons, we sometimes need to get local variables within a function. However, as mentioned earlier, this is not possible under normal circumstances and can only be achieved by workaround.
That is, in the interior 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 within the function F1, when all local variables within F1 are visible to F2. But the reverse is not, F2 internal variables, the F1 is not visible. This is the "chained scope" structure (chain scope) peculiar to the JavaScript language.
The child object looks up the variables of all the parent objects at a level. Therefore, all the variables of the parent object are visible to the child, and the opposite is not true.
Since F2 can read local variables in F1, we can not read the internal variables of the F2 as long as the return value.
JS Code
Function F1 () {
n=999;
function F2 () {
alert (n);
}
return F2;
}
var result=f1 ();
Result (); 999
--------------------------------------------------------------------------------------------------------
third, 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 internal variables of other functions.
Because in a JavaScript language, only a child function within a function can read a local variable, the closure can be simply understood as "a function defined within a function."
So, in essence, closures are a bridge that connects functions inside and outside functions.
--------------------------------------------------------------------------------------------------------b
Iv. use of closures
Closures can be used in many places. Its maximum use is two, one is the previous mentioned can read the function inside the variable, the other is to keep the values of these variables always in memory.
How to understand this sentence. Take a look at the code below.
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 piece of code, result is actually the closure F2 function. It runs two times, the first value is 999, and the second value is 1000. This proves that the local variable n in the function F1 is kept in memory and is not automatically purged after the F1 call.
Why is that so? 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 the presence of F2 depends on F1, so F1 is always in memory and will not be reclaimed by the garbage collection mechanism (garbage collection) after the call has ended.
Another notable part of this code is the "Nadd=function () {n+=1}" line, which first nadd not use the var keyword, so nadd is a global variable, not a local variable. Second, the value of the Nadd is an anonymous function (anonymous functions), and the
The anonymous function itself is also a closure, so the nadd is equivalent to a setter, which can manipulate local variables within the function outside the function.
--------------------------------------------------------------------------------------------------------
Five, use the closure of the attention point
1 because the closure will make the function of the variables are stored in memory, memory consumption is very large, so can not abuse the closure, otherwise it will cause Web page performance problems, in IE may lead to memory leaks. The workaround is to remove all unused local variables before exiting the function.
2 The closure will change the value of the inner variable of the parent function outside the parent function. So, if you use the parent function as an object, using the closure as its common method, and the internal variable as its private property (private value), be careful not to
Change the value of a variable within the parent function.
--------------------------------------------------------------------------------------------------------
VI. Study Questions
If you can understand the operating results of the following code, you should understand the closure mechanism.
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 code above is wrong. The scope of the Innerfun () is called Inside the Outerfun () and it is wrong to invoke it outside the Outerfun ().
Change to the following, which is the closure:
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 closure:
When an intrinsic function is referenced outside the scope that defines it, the closure of the internal function is created, and if the intrinsic function references a variable that is located in an external function, the variables are not freed in memory when the external function is called, because the closures require them.
--------------------------------------------------------------------------------------------------------
let's look at an 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 the function to maintain a scope 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, because the VAR keyword is not used, the assignment operation is linked to the Var a=4 along the scope; and change its value.
--------------------------------------------------------------------------------------------------------------- -----------------------------------
If you are not very understanding of JavaScript closures, please see the following reproduced article: (Reprint: http://www.felixwoo.com/archives/247)
One, what is closure.
The official explanation is that a closure is an expression (usually a function) that has many variables and an environment that binds them, and therefore these variables are also part of the expression.
I believe very few people can read this sentence directly, because he describes too academic. In fact, this sentence is in layman's terms:
all function in JavaScript is a closure。 In general, however, nested function results in a more powerful closure, which is what we call "closures" most of the time. Look at the following code:
function A () {
var i = 0;
Function B () {alert (++i);}
return b;
}
var C = a ();
C ();
This code has two features:
1. The function b is nested inside function A;
2, function a returns function B.
The reference relationship is shown in figure:
So after the Var c=a () is executed, the variable C actually points to function B, then executes C () and pops up a window showing the value of I (first time 1). This piece of code actually creates a closure, why. Because the variable C outside function A refers to function B within function A, that is to say:
a closure is created when the internal function B of function A is referenced by a variable outside function a.
Let's talk a little more thoroughly. A "closure" is a method function in the constructor body that defines another function as the target object, 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 the temporary variables used by the original constructor body as long as the target object retains its method throughout its lifetime. Although the first constructor call has ended, the name of the temporary variable disappears, but the value of the variable is always referenced within the target object's method, and the value can only be accessed through this method. Even if you call the same constructor 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.
second, the closure of what role.
In short, the function of a closure is that after a is executed and returned, the closure makes the JavaScript garbage collection mechanism GC not reclaim the resource occupied by a, because the execution of the internal function B of a relies on the variables in a. This is a very straightforward description of the closure function, unprofessional and not rigorous, but the general meaning is that, understand the closure requires a step-by-step process.
In the above example, because the closure makes function a return, I always exist in a, so each C (), I is the value of alert out I after 1.
So let's imagine the other case, if a returns a function B, the situation is completely different. Since A is executed, B is not returned to the outside of a, but is referenced by a, while a is only referenced by B, so functions A and B refer to each other without being disturbed by the outside world (referenced by the outside world), and functions A and B are recycled by GC. (The garbage collection mechanism for JavaScript is described later in detail)
the microscopic world in closures
To get a deeper understanding of the relationship between closures and function A and nested function B, we need to introduce several other concepts: the execution Environment for functions (excution context), active objects (call object), scope (scope), scope chain. Use function A as an example to illustrate these concepts from the process of definition to execution. When
definitionFunction A, the JS interpreter will have the function
Scope Chain (scope chain)Set to
define the "environment" where A is, if a is a global function, only the window object is in scope chain. When
PerformFunction A, a will enter the corresponding
Execution Environment (excution context)。 When you create an execution environment, you first add a scope attribute for a, which is the
Scope, the value is the scope chain in step 1th. That is, the scope chain of the a.scope=a. The execution environment then creates a
Active object (call object)。 The active object is also an object that has attributes, but it does not have a prototype and is not directly accessible through JavaScript code. After the active object is created, the active object is added to the top of the scope chain of a. At this point A's scope chain contains two objects: A's active object and a Window object. The next step is to add a arguments property on the active object that holds the arguments passed when the function A is invoked. Finally, the reference of all function A and the internal function B are added to the active object of a. In this step, the definition of function B is complete, so as in step 3rd, the scope chain of function B is set to the environment defined by B, that is, the scope of a.
In this, the entire function A is completed from the definition to the execution step. At this point a returns the reference of 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, function B is dependent on function A, so function A is not reclaimed by GC after it returns.
When function B is executed it will be similar to the above steps. Therefore, the scope chain of B at execution time contains 3 objects: The active object of B, the active object of a, and the Window object, as shown in the following illustration:
As shown in the figure, when you access a variable in function B, the search order is to search for its own active object, if it exists, to return it if it does not exist, and then to search until it is found. If a prototype prototype object exists in function B, it looks for its own prototype object after searching for its own active object, and then continues to find it. This is the variable lookup mechanism in JavaScript. Returns undefined if the entire scope chain is not found.
Summary, there are two important words mentioned in this paragraph: function of
definitionAnd
Perform。 It is mentioned that the scope of the function is defined at the time of defining the function, rather than being determined at the time of execution (see steps 1 and 3). Use a piece of code to illustrate the problem:
function f (x) {
var g = function () {return x;}
return g;
}
var h = f (1);
The variable h in this code points to the anonymous function in F (returned by G). Assuming that the scope of function h is determined by execution alert (h ()), then H's scope chain is the active object->window object->alert the active object of H. Suppose that the scope of function h is defined at definition, that is, the anonymous function that H points to defines the scope. Then, at the time of execution, H's scope chain is: H's active object->f the active object->window object.
If the first hypothesis is established, the output value is undefined; if the second assumption is true, the output value is 1.
The results of the operation prove that the 2nd hypothesis is correct, stating that the scope of the function is indeed defined when defining the function.
Four, closures the application scene
Protect variable security within a function. Take the first example, in function A, I have only function B to access, and I cannot access it through other means, thus protecting the security of I. Maintain a variable in memory. As in the previous example, because of the closure, function A has always been in memory, so every time C () is executed, I will add 1 to my self. JS private Property and private method (cannot be accessed externally) through protection of variable security
Private properties and methods cannot be accessed outside of constructor
Function Constructor (...) {
var that = this;
var membername = value;
function MemberName (...) {...}
}
The above 3 points are the most basic application scenarios for closures, and many classic cases derive from this.
five, JavaScript garbage collection mechanism
In JavaScript, if an object is no longer referenced, the object is reclaimed by GC. If two objects are referenced to each other and are no longer referenced by the 3rd, then the two referenced objects are also reclaimed. Because function A is referenced by B, B is referenced by C outside of a, which is why function A is not recycled after it executes.
Six, the conclusion
Understanding JavaScript closures is the way to advanced JS programmers, understanding their interpretation and operational mechanisms to write more secure and elegant code.