On JavaScript nesting function and closure _javascript skills

Source: Internet
Author: User
Tags anonymous closure garbage collection
"Nested Functions"
JavaScript allows embedded functions that allow functions to be used as data, and under the function lexical scope, can produce amazing places that differ from traditional object-oriented languages.
First, the function of JavaScript is to divide the scope by lexical. Instead of dynamically dividing scopes, functions are run in the scope that defines them, not in the scope in which they are executed, so when the nested function and its peripheral functions are defined in the same lexical scope, is very easy to understand. For example, the following very prosaic code:
Copy Code code as follows:

var x = ' Global ';
function f () {
var x = ' local ';
function g () {
alert (x);
}
g ();
}
f (); ' Local '

When F () is invoked, the scope chain can be understood to consist of two parts, containing the call object of F, which is followed by the global object. Looking for the value of x, it looks in the call object from F first, and if not, looks for x in the following global object. Similarly, g because it is a nested function of f, then, when G is called, the scope chain should be composed of three parts, the call object of G, the call object of F, and the global object. function g is to output the value of x, so we'll look for the value of x in the Call object of G, there's no definition in G, then look for the definition of x in the outer f call object, and then find the x= ' local ', then output x instead of looking at the global object further down. If the value of x is not defined in F, it will continue to look for the global object following the scope chain, and the result is global. If there is no definition in the global object, then nature is undefined.
Well, we have a preliminary understanding of the scope chain, at the same time we know that closures have two more common uses, one that can be used to access local variables, and the other is to store variable values in its peripheral scope in memory without destroying the function call.
Here's a look at a bland example that might help to understand why closures can store external variables in memory.
Copy Code code as follows:

function Makefunc (x) {
return function () {return x + +}
}
var a = [Makefunc (0), Makefunc (1), Makefunc (2)];
Alert (A[0] ());
Alert (A[1] ());
Alert (A[2] ());

The result is 0,1,2, and there is nothing special about it, which is also the normal manifestation of the strict lexical scope. Each time the Makefunc call completes, its calling object is removed from the scope chain, and no reference to it ends up with garbage collection. In detail, we can understand this.
Makefunc creates a call object for him to put into the scope chain each time it is invoked. For Makefunc This function, this invocation object contains a property x (that is, a function argument, because the function argument can be viewed as a property of the calling object), Makefunc returns a reference to an anonymous nested function, which is then executed by the anonymous nested function, and creates a calling object. Into the scope chain, the anonymous function returns the value of X, (note: There is no X in the calling object of the anonymous function, so it refers to the calling object of the function Makefunc on its periphery, accesses to X) and then x plus 1, so that the anonymous function completes, and it calls the object to remove from the scope chain. The Makefunc is then executed, and the Makefunc call object is also removed. Because its calling object contains X, X is also destroyed as it is destroyed. Will not be saved.
The above is the detailed implementation of the function, please carefully understand the following changes to see the code:
Copy Code code as follows:

var x = 0;
function Makefunc () {
return function () {return x + +}
}
var a = [Makefunc (), Makefunc (), Makefunc ()];
Alert (A[0] ());
Alert (A[1] ());
Alert (A[2] ());

Now x is a global variable, and the result is 0,1,2, but the result is somewhat different from the one above. Here we also understand the cause of this result from the direction of the scope chain.
Similarly, Makefunc creates a calling object into the scope chain each time it calls, because it returns a reference to the internal nested function, so the internal nested function starts executing and creates a call object for the nested function to the scope chain. And then return the value of X, note that this is different, and there is no X in the calling object of the nested function. There is no x in the Makefunc call object on its periphery, only to go down to the global object, find the definition of X in the global object, execute normally, return the value of x, X plus 1, and then the nesting function completes, The calling object is removed, then the Makefunc is finished, the calling object is removed, but because none of their calling objects have X, their call object destruction does not affect x at all. As a result, the change of the global variable x value is preserved.
Note that the call object that is used to access the perimeter above is intended only to help understand, but not strictly, that JavaScript does not directly access the calling object in any way, but that it defines a property as part of the scope chain of the calling object or "alive." In addition, if a peripheral function contains two or more nested functions that have references to global objects, the nested functions share the same global invocation object, and one of the changes to the global object is visible to the other.
Well, in JavaScript, a function is a synthesis of the code to be executed and the scope that executes the code, and broadly speaking, we can call this code and the scope complex a closure.
"Closures"
We occasionally need to write a function that needs to be tuned to remember a variable's value. So, if we understand the scope, we know that local variables are hard to do because the calling object of the function cannot be maintained after the call. Global variables can be done, as in the example above, but this is very easy to cause global variable pollution. Since the calling object cannot be maintained, then we do not save the value in the calling object. So, here's one way to do this: save it with the properties of the function object itself.
Copy Code code as follows:

UniqueID = function () {
if (!arguments.callee.id) arguments.callee.id = 0;
return arguments.callee.id + +;
}
Alert (UniqueID ()); 0
Alert (UniqueID ()); 1

As above, because the function itself is an object, it is possible to preserve it by using one of its own attributes, but there is a problem that anyone can force access to the value we originally saved and make changes at any time by Unqueid.id. This is what we don't want to see.
So, usually, we use closures to implement this. As follows:
Copy Code code as follows:

_uniqueid = (function () {
var id = 0;
return function () {return id + +}
})();
Alert (_uniqueid ()); 0
Alert (_uniqueid ()); 1

Similarly, we also use the link field to explain the result. Notice that _uniqueid itself is an anonymous function, and there is an anonymous nested function inside, which we call directly _uniqueid (), that is, we directly call the nested function inside the _uniqueid, and its calling object has no ID defined. The ID in the calling object that refers to the perimeter is then returned, ID plus 1, and the inner nested function call object moves out of the scope chain. The perimeter ID was not destroyed, so it was saved.
One might wonder, not to say that the calling object removes the scope chain after the function has finished executing, the peripheral anonymous function (function () {}) (), and the call is complete, and the object should be called.
Yes, the calling object ends the reference at the end of the current function, but do not misunderstand the call above _uniqueid (), which is not a direct call to the outer function, but rather a nested function called, and the scope chain of the nested function is the scope chain of the enclosing function. So when its calling object removes the scope chain, it is able to access the properties of the other objects on the scope chain and change it.
Closure itself is a difficult to understand but very useful things, hoping to have some help for those in need. In addition, the qualifications are limited, I understand may be wrong, if found, please correct me.
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.