JS anonymous function closure

Source: Internet
Author: User

function declaration: Functions functionname (ARG0,ARG1) {//function body} function expression: var functionname = function (ARG0,ARG1) {//function body} The main difference between a function declaration and a function expression is that the former is loaded into the scope before the code executes, and the latter is defined when the code executes to that line. Another difference is that the function declaration assigns a name to the function, and the function expression creates an anonymous function and assigns the function to a variable1 recursive recursive functions are formed when a function calls itself by name, for example: function factorial (num) {if (num<=1) {return 1;   } else{return num*factorial (num-1); }}there seems to be no problem with the classic recursive factorial function above, but the following code can cause it to go wrong:var anotherfactorial = factorial;   factorial = null;   Alert (Anotherfactorial (4)); Error The above code first saves the factorial () function in the variable anotherfactorial, then sets the factorial variable to null, and the result points to the original function's reference with only one left. However, when Anotherfactorial () is called Next, the factorial () must be executed, and factorial is no longer a function, resulting in an error.using Arguments.callee in this case can solve this problem。Arguments.callee Initial value is just being executedfunction object for anonymous functions 2 closure Nicholas that a closure refers to a function that has access to a variable in another function scope. A common way to create closures is to create another function inside one function, taking the createcomparisonfunction () function as an example: function Createcomparisonfunction (PropertyName) {return function (OBJECT1,OBJECT2) {var value1 = object1[propertyname];var value1 = object2[propertyname];        if (value1 < value2) {return-1;}         else if (value1>value2) {return 1;}         else {return 0;}    };} The two lines of code in red above are the code in an intrinsic function (an anonymous function) that accesses the variable propertyname in the external function. Even if the intrinsic function is returned and is called elsewhere, it can still access the variable propertyname. This variable is also accessible because the scope of the inner function's scope chain contains the scopes of Createcomparisonfunction ().    when a function is called for the first time, an execution environment and the corresponding scope chain are created, and the scope chain is assigned to a special internal property (that is, [[Scope]]). The function's active object is then initialized with the values of this, arguments, and other named parameters. In a scope chain, however, the active object of the outer function is always second, until the global execution environment at the end of the scope chain.     during function execution, to read and write the value of a variable, you need to look for the variable in the scope:    function compare (value1,value2) {      if (value2<value2) {            return-1;    }     else if (value1>value2) {           return 1;    }      else {        return 0;    }   }    var result = Compare (5,10);    The above code first defines the compare () function and calls it at the global scope. The first time you call compare (), you create an active object that contains this, arguments, value1, value2. The variable object for the global execution Environment (including This,result,compare) is in the second position in the scope of the Compare () execution Environment, 

Each execution environment in the background has an object that represents a variable-the variable object. Variable objects for the global environment always exist, while variable objects for local environments such as the Compare () function exist only during function execution. When you create the Compare () function, a scope chain is created that contains the global variable 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, an active object (used 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. A scope chain is essentially a list of pointers to variable objects that only reference but do not actually contain variable objectsin general, when the function is finished, the local active object is destroyed, only the global scope is stored inside, but the closure is different. A function defined internally by another function adds the active object containing the function to its scope chain. Therefore, in the scope chain of the anonymous function defined within the createcomparisonfunction () function, it will actually contain the active object of the external function createcomparisonfunction ().var compare = createcomparisonfunction ("name");var result = Compare ({name: ' Nicholas '},{name: "Greg"});


 After the anonymous function is returned from Createcomparisonfunction (), its scope chain is initialized to the active object and the global variable object that contains the Createcomparisonfunction () function. So Createcomparisonfunction () the active object is not destroyed after the function is executed because the scope chain of the anonymous function is still referencing the active object。In other words, after 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.Closures and variablesThis configuration mechanism of the scope chain leads to a noticeable side effect, that is, the closure can only get the last value of any variable in the containing function. Because the closure holds the entire variable object, not a particular variable.    function createfunctions () {var result = new Array ();   for (Var i=0;i<10;i++) {Result[i] = function () {return i;} } return result; var funcs = Createfunctions (), for (Var i=0;i<funcs.length;i++) {document.write (Funcs[i] () + "<br/>");}    Outputs 10 10 This may be fixed by changing the code in the first for loop to the following code: Result[i] = function (num) {return function () {return num; }} (i);about this objectThe This object is a function-based execution environment binding at run time.: in a global function, this equals window, and when the function is called as a method of an object, this is equal to that object. However, the execution environment of an anonymous function is global, so its this object usually points to window. Of course, this will point to other objects when the function execution environment is changed by call () or apply (). var name = "the window"; var object={name: ' My object ', Getnamefunc:function () {return function () { return this.name;        }}}alert (Object.getnamefunc ()); "The window" because each function is called, its active object automatically gets two special variables: this and arguments, the intrinsic function searches for these two variables only to find its active object until then, of course,       You can modify the Getnamefunc to function () {var. = this;       return function () {return that.name; }} This will allow you to access the object.Memory LeaksBecause IE uses different garbage collection routines for JScript objects and COM objects, closures can cause problems in IE. Specifically, if an HTML element is stored in the closure scope chain, it means that the element will not be destroyed: function Assignhandler () {    var element = document.getelementbyidx_x_x_x_x_x_x_x_x (' someelement ');     element.onclick = function () {        alert (element.id);   &nbsp}} The above code creates a closure that is the event handler for element elements. And this closure creates a circular reference. Because the anonymous function holds a reference to the active object of Assignhandler (), it causes the reference count of element to not be reduced. As long as an anonymous function exists, element has a reference number of at least 1, so that the memory it consumes will never be recycled. But can be modified as follows: function Assignhandler () {    var element = document.getelementbyidx_x_x_x_x_x_x_x_x (' Someelement ');     var id = Element.id;    element.onclick = function () {         alert (ID);    }    element = null;} In the above code, the element.id copy is saved in a variable, and the variable referenced in the closure eliminates the circular reference. However, this is not enough to resolve a memory leak because the closure references the entire active object that contains the function, which contains element. Even if the closure does not directly refer to element, a reference is still saved in the active object that contains the function. It is therefore necessary to set the element variable to null. This makes it possible to de-reference the DOM object and smoothly reduce itsThe number of references to ensure that the memory it occupies is properly reclaimed.  mimic block-level scopesThe syntax for an anonymous function that is used as a block-level scope (often referred to as a private scope) is as follows: (function () {}), var functionname = function () {} (); The syntax that executes immediately after the function expression definition is correct, but function () {} () will be faulted, because JavaScript treats the Function keyword as the beginning of a declaration of functions, the function declaration cannot be followed by parentheses. The function expression can be followed by parentheses. To convert a function declaration to a function expression, simply add a pair of parentheses:(function () {}) () Any variables defined in the anonymous function are destroyed at the end of execution. In large applications involving many developers, creating private scopes allows each developer to use their own variables without worrying about messing up the global scope.Private VariablesVariables defined in any function can be considered private variables because they cannot be accessed outside of the function. Private variables include the parameters of the function, local variables, and other functions defined inside the function. If you create a closure inside a function, the closures can also access these variables through their own scope chain, which allows you to create only methods to access the private variables. We refer to public methods that have access to private variables and private functions as privileged methods. There are two ways to create a privileged method on an object. The first is to define the privileged method in the constructor:function MyObject () {var privatevariable = 10;   function Privatefunction () {return false; } This.publicmethod= function () { //global variableprivatevariable++;    return Privatefunction (); After creating the MyObject instance, there is a drawback to defining the privileged methods in the constructor, except that there is no way to directly access privatevariable and Privatefunction () in addition to using Publicmethod ().   That is, you must use the constructor pattern to achieve the purpose of static private variables: By defining private variables or functions in a private scope, you can also create privileged methods, which are as follows: (function () {//private variable and private function var privatevariable = 10;   function Privatefunction () {return false; }//ConstructorsMyObject = function () {};Public/Privileged Method MyObject.prototype.publicMethod = function () {privatevariable++;   return Privatefunction (); }) (); This pattern creates a private scope in which a constructor and the corresponding method are encapsulated. In a private scope, private variables and private functions are defined first, and then the constructors and their public methods are defined. The public method is defined on the prototype, which is the prototype pattern. It is important to note that this pattern uses function expressions instead of function declarations when defining constructors.function declarations can only create local functions, and for the same reason MyObject is created for global variables. Module mode: The preceding pattern is used to create private variables and privileged methods for the custom type. The module mode is to create private variables and privileged methods for the singleton. The so-called Singleton refers to an object that has only one instance.     var singleton={name:value, Method:function () {}} module mode can be enhanced by adding private variables and privileged methods to a single case, with the following syntax: var singleton = function () {     var privatevariable = 0;     function Privatefunction () {return false;}     Privileged/public methods and properties return {publicproperty:true, return privatefunction (); }} (); This module pattern uses an anonymous function that returns an object. Inside this anonymous function, the private variables and functions are defined first. The direct amount of an object is then returned as the value of the function. the returned object's direct amount contains only properties and methods that can be exposed. Because this object is defined inside an anonymous function, its public methods have access to private variables and functions. Essentially, this object is defined by the direct volume common interfaces for single cases。 This pattern is useful when you need to perform some initialization of a singleton, while maintaining its private variables. For example: function Basecomponent () {}function othercomponent () {}var application = function () {      var components = new Array ();   //private variables and functions      //initialize      components.push (new Basecomponent ());      //Public      return{           getcomponent:function () {return components.length;},           registercomponent:function (component) {              if (typeof component = = "Object") Components.push (component);           }      }      } (); In a Web application, you often need a single example to manage application-level information. This example creates a application object for managing the component. In general, you can use module mode if you want to create an object and initialize it with some data, and also expose some methods to access private data.   Enhanced module mode: Suitable for those cases where the singleton must be a certain type of instance while alsoIt is necessary to add some properties and methods to enhance the situation. If the Application object in the example above should be an instance of Basecomponent, the following code is available: var application=function () {    var components = New Array ();     components.push (new Basecomponent ());     var app = new Basecomponent ();     app.getcomponentcount = function () {        return components.length;     }    app.registercomponent = Function (component) {       if (typeof component = = ' object ') {            components.push (component);        }    }    return app;} ();

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.