This article mainly introduces JavaScript anonymous functions and closures. If you need them, you can refer to anonymous functions: functions without names;
Closure: a function that can access variables in a function scope;
An anonymous Function
// Normal function box () {// The function name is box; return 'lil';} box (); // => Lee; call the function; // anonymous function () {// anonymous function, an error is returned; return 'lil';} // self-Execute (function (name) {console. log (name); // => Lee;}) ("Lee"); // "()" indicates that the function is executed and parameters can be passed; // assign an anonymous function to the variable var box = function () {// assign the anonymous function to the variable; return 'lil' ;}; console. log (box (); // The call method is similar to the function call; // The anonymous function box () {return function (name) in the function) {// an anonymous function in the function that generates a closure; return name ;};}; console. log (box () ("Lee"); // function box () calls an anonymous function and transmits parameters;
Second Closure
Closure: a function with the right to access variables in another function scope;
Common method of creating a closure: create another function within a function; access the local variable of the function through another function;
// The closure can return the local variable function box () {var user = 'lil'; return function () {// return the local variable user of box () through the anonymous function; return user ;};} console. log (box (); // => Lee; directly call box () to obtain the return value of the anonymous function; var B = box (); console. log (B (); // => Lee; another method for calling anonymous functions; // advantage: local variables can be resident in the memory to avoid using global variables; // (global variable contamination leads to unpredictable applications, and every module call will inevitably lead to disasters. Therefore, private and encapsulated local variables are recommended );
// Disadvantage: // use global variables to accumulate var age = 100; // global variables; function box () {age ++; // global variables can be called at the module level, accumulate;}; box (); // execute the function, accumulate once; console. log (age); // => 101; Output global variable; box (); // Execute function, accumulate once; console. log (age); // => 102; Output global variables; // you cannot accumulate function box () {var age = 100; age ++ through local variables; // implement accumulation; return age;} console. log (box (); // => 101; console. log (box (); // => 101; it cannot be accumulated because the age variable in the function is initialized again when the function is called for the second time; // you can use closures to accumulate local variables. Box () {var age = 100; return function () {// accumulate in the anonymous function; age ++; return age; // return the accumulated variable ;}; // at this time, the age value of the local variable of the box () function has been changed to the value after accumulation;} var B = box (); // give box () function is assigned to the variable; console. log (B (); // => 101; call the anonymous function, accumulate once; console. log (B (); // => 102; the second call to the anonymous function is added twice; // PS: because the partial variable resources returned by the scope in the closure will not be destroyed and recycled immediately, it may occupy more memory. Excessive use of the closure will lead to lower performance; (The closure can be referenced in the "private scope" to destroy the variable.) // the mechanism of the scope chain causes a problem, any variable obtained by the anonymous function in the loop is the last value ;?
// The loop contains the anonymous function box () {var arr = []; for (var I = 0; I <5; I ++) {// when the declared variable I = 5, the loop stops. In this case, the variable I = 5 in the loop; arr [I] = function () {// What arr [I] gets is the unexecuted anonymous function () {}; return I ;}; return arr; // arr = [function, function, function, function, function];} var B = box (); // => [function, function]; returns the array arr returned by function box; console. log (B. length); // => 5; get the array length of the function set; for (var I = 0; I
5, 5, 5, 5; the output value of each function is the last value;} // The output result of the above example is 5, that is, the maximum I value obtained after the loop; // because B [I] calls anonymous functions, they are not self-executed. By the time of the call, box () has been executed and I has already changed to 5; // The loop contains the anonymous function-Change 1 and self-execute the anonymous function box () {var arr = []; for (var I = 0; I <5; I ++) {arr [I] = (function (num) {// arr [I] returns the result value 0-4 after the anonymous function is executed; return num;}) (I); // self-executed and passing parameters;} return arr;} var B = box (); // =>, 4]; B indicates the array returned by box (); for (var I = 0; I <B. length; I ++) {console. log (B [I]); // 0 1 2 3 4; here the returned value is a value;}; // In the example, let the anonymous function execute itself, as a result, the array instead of the function is returned to a [I], and the values 0, 1, 2, 3, and 4 are retained in B [0]-B [4; // The loop contains an anonymous function-Change 2, and an anonymous function is created in the anonymous function; function box () {var arr = []; for (var I = 0; I <5; I ++) {arr [I] = (function (num) {return function () {// return function; return num ;}}) (I);} return arr; // arr = [function, function];} var B = box (); for (var I = 0; I <B. length; I ++) {console. log (B [I] (); //, 2, 3, 4;}; // In change 1 and Change 2, we use anonymous functions for self-execution, immediately assign the result to arr [I]; // each I is passed by the caller by value. Therefore, the final returned result is the specified incremental I instead of the box () variable I in the function;
3. this object
// Using this object in the closure may cause some problems; this object is bound to the function-based execution environment at runtime; // if this is globally pointed to window, if it points to this object inside the object; // while the closure points to the window at runtime, because the closure does not belong to the property or method of this object; var user = 'windows '; var obj = {user: 'object', getUserFunction: function () {return function () {// The closure does not belong to obj. this in it points to window; return this. user ;}}}; console. log (obj. getUserFunction (); // => Window; // You can forcibly point to an object console. log (obj. getUserFunction (). call (obj); //> Object; // you can also get the Object getUserFunction: function () {var that = this from the previous scope; // obtain this from the object method. At this time, that points to the obj object; return function () {return that. user ;}} console. log (obj. getUserFunction (); // => Object;
Memory leakage
// Because the JScript object and DOM object of IE use different garbage collection methods, the closure in IE may cause memory leakage, that is, the elements residing in the memory cannot be destroyed; function box () {var oDiv = document. getElementById ('odiv '); // The oDiv stays in the memory after it is used up; oDiv. onclick = function () {alert (oDiv. innerHTML); // here oDiv causes memory leakage;}; oDiv = null; // unreference;} box (); // Since the anonymous function saves a pair of box () therefore, the number of oDiv references cannot be reduced. // as long as an anonymous function exists, the oDiv reference number must be at least 1; therefore, the memory it occupies will never be recycled; // PS: If the reference is not removed, it will be released only after the browser is closed;
5. Simulate block-level scopes (define and call an anonymous function immediately)
// JS does not have the block-level scope concept; // This means the variables defined in the block statement (for statement/if statement, it is actually created in the include function instead of the statement; function box (count) {for (var I = 0; I
Count = 2; I = 2 when the cycle is stopped, at this time I = 2; console. log (I); // => 2; I will not expire when I leave the for block;} box (2); function box (count) {for (var I = 0; I
[1, 2, 3, 4]; box is not recognized;}) (); // destroys the variables in the anonymous function; console. log (box); // => box is not defined; // using block-level scopes in global scopes can reduce the memory usage of closures; because there is no reference pointing to an anonymous function // as long as the function execution is complete, the scope chain can be destroyed immediately;
Six private variables
// JavaScript does not use the concept of private attributes; all attributes are public; // There is a concept of private variables: variables defined in any function, these variables can be considered private variables because they cannot be accessed outside the function; // Private variables include the function parameters/local variables and other functions defined within the function; function box () {var age = 100; // Private variables, which cannot be accessed externally;} // when a closure is created internally, the closure can also access these variables through its own scope chain; // with this, you can create a public method for accessing private variables; privileged method; function Box () {// constructor; var age = 100; // Private variable; function run () {// Private function; return 'running... ';}; this. get = function () {// a public privileged method; return age + run (); // assign the closure value to the variable; };} var box = new Box (); console. log (box. get (); // you can use the constructor to transmit parameters to access the private variable function Person (name) {var user = name; // this statement can be omitted; this. getUser = function () {return user;}; this. setUser = function (name) {user = name;} var p = new Person ('lil'); console. log (p. getUser (); // => Lee; console. log (p. setUser ('jack'); console. log (p. getUser (); // => Jack; // However, the constructor mode creates the same group of new methods for each instance; this problem can be avoided by using static private variables to implement privileged methods;
Seven static private variables
// Define private variables or functions in block-level scopes (Private scopes). You can also create public privileged methods. (function () {// create private scopes; var age = 100; // static private variable; function run () {return 'running... ';}; Box = function () {}; // use a function expression to define the constructor; Box. prototype. go = function () {// public (privileged) method; defined on the prototype; return age + run ();};})(); var box = new Box (); console. log (box. go (); // 100 running ...; // The above object Declaration uses Box = function () {} Instead of functiong Box () {}; and The var keyword is not used when the Box is declared // cause: initialization of undeclared variables always creates A global variable. Therefore, Box becomes a global variable that can be accessed outside of the private scope. // If a constructor is defined using a function declaration, it becomes a private function, it cannot be accessed globally, so you need to use the function to define the constructor; (function () {var user = ""; Person = function (value) {// The Person defined here is a global variable; user = value; // The constructor here has the right to access the private variable name;}; Person. prototype. getUser = function () {return user;}; Person. prototype. setUser = function (value) {user = value ;}}) (); var person = new Person (); person. setUser ('lil'); console. log (person. GetUser (); // => Lee; // If prototype is used, the method is shared, and the user becomes a static attribute. // the so-called static attribute: that is, attributes shared with different objects ;?
Eight-module Mode
// In short, if you must create an object and initialize it with some data, and expose some methods that can access the private data, you can use the module mode; // previously, the constructor method was used to create private variables and privileged methods. // The object literal method was created in the module mode; var box = {// literal object, also a singleton object: object with only one instance; age: 100, // This is a public attribute and will be changed to private; run: function () {return 'running... ';};}; // module mode private variables and functions: var box = function () {var age = 100; function run () {return' running... ';} return {// return a literal object as a function value; go: function () {// The returned object literal contains only publicly available attributes and methods; return age + run (); // because this object is defined within an anonymous function, its public method has the right to access private variables and functions ;}}; // essentially, this object literally defines the public interface of the singleton;} (); // This mode requires initialization of the Singleton, at the same time, it is very useful to maintain its private variables. // the example of directly returning the object above can also be written as follows: var box = function () {var age = 100; function run () {return 'is running... ';} var obj = {// create a literal object; go: function () {return age + run () ;}}; return obj; // return the newly created object;} (); // literal object declaration, which can be considered as a singleton mode in design mode; // The so-called Singleton Mode means that only one instance of the object is always maintained; // enhanced module mode: Suitable for returning custom objects, that is, constructors; function Desk () {}; var box = function () {var age = 100; function run () {return 'is running... ';}; var desk = new Desk (); desk. go = function () {return age + run () ;}; return desk ;}(); console. log (box. go (); // => 100 running;
Summary
In JavaScript programming, function expressions are a very useful technique. Using function expressions can achieve dynamic programming without having to name functions;
1. function expression
The function expression is different from the function declaration. The function Declaration requires a name, but the function expression does not;
A function expression without a name is called an anonymous function. 2. Closure
When other functions are defined in the function, the closure is created. The closure has the right to access all variables in the function. The principle is as follows:
In the background execution environment, the scope chain of a closure contains its own scope, the scope of the function, and the global scope;
Generally, the function scope and all its variables are destroyed after the function is executed;
However, when a function returns a closure, the function's scope will remain in the memory until the closure does not exist. 3. Block-level scope
Using closures can mimic block-level scopes in JavaScript (JavaScript itself does not have block-level scopes). The main points are as follows:
Create and call a function immediately, so that you can execute the code and leave no reference to the function in the memory;
The result is that all variables in the function will be destroyed immediately-unless some variables are assigned to variables in the include scope (that is, the external scope); 4. Private Variables
Closures can also be used to create private variables in objects. The main points are as follows:
Even if JavaScript does not have the concept of true private object attributes, you can use closures to implement public methods, while using public methods can access variables defined in the scope;
The constructor mode and prototype mode can be used to implement custom privileged methods, or the module mode can be used to implement the single-instance privileged methods;