Preface
When you are learning JavaScript, you often encounter code for self-execution of anonymous functions. Today we will focus on self-execution.
Before learning about this in detail, let's talk about the "self-execution" method. This article is not necessarily quite right about this function. It mainly depends on how you understand it, some people say immediate calls, some say automatic execution, so you can get a name according to your own understanding, however, I have heard many people call it "self-executed", but I have mentioned a lot later to persuade everyone to call it "function expressions that are called immediately ".
Address: http://benalman.com/news/2010/11/immediately-invoked-function-expression/
What is self-execution?
In JavaScript, any function creates an execution context during execution, because the variables and functions declared for the function may only be within the function, when calling a function, a simple method is provided to create a free variable or a private sub-function.
Copy codeThe Code is as follows:
// Because this function returns another function, the function can access the free variable I
// All said, this internal function actually has the permission to call internal objects.
Function makeCounter (){
// I can only be accessed within makeCounter
Var I = 0;
Return function (){
Console. log (++ I );
};
}
// Note that counter and counter2 are different instances with their own I.
Var counter = makeCounter ();
Counter (); // logs: 1
Counter (); // logs: 2
Var counter2 = makeCounter ();
Counter2 (); // logs: 1
Counter2 (); // logs: 2
Alert (I); // reference error: I does not have defind (because I exists in makeCounter ).
In many cases, multiple makeCounter instances are not required. In some cases, the returned values do not need to be displayed.
Core issues
When you declare a function similar to function foo () {} Or var foo = function () {}, You can implement self-execution by adding an arc to the end, for example, foo (), check the Code:
Copy codeThe Code is as follows:
// If you want to add an arc () to the first declared function, you can execute it yourself, for example, foo (),
// Because foo is only a reference to the function () {/* code */} expression
Var foo = function () {/* code */}
//... Does it mean that an arc can be automatically executed after it is added?
Function () {/* code */} (); // SyntaxError: Unexpected token (
//
If the above Code is even run, 2nd code errors will occur, because when the parser parses the global function or the function internal function keyword, the function declaration is considered by default, rather than the function expression, if you do not show it to the compiler, it will be declared as a function without a name by default, and a syntax error message will be thrown, because the function Declaration requires a name.
Narration: function, paren, and SyntaxError)
Interestingly, even if you add a name for the above error code, it will prompt a syntax error, but it is different from the above. When parentheses () are added to an expression, the expression is executed immediately, but parentheses () are added to the end of a statement. This is totally different. It is just a grouping operator.
Copy codeThe Code is as follows:
// The following function is correct in syntax, but it is still a statement.
// An error will still be reported after parentheses () are added, because the grouping operator must contain an expression.
Function foo () {/* code */} (); // SyntaxError: Unexpected token)
// However, If you input an expression in arc (), no exception will be thrown.
// But the foo function will not be executed
Function foo () {/* code */} (1 );
// Because it is equivalent to the following code, a function declaration is followed by a non-relational expression:
Function foo () {/* code */}
(1 );
You can access ECMA-262-3 in detail. Chapter 5. Functions for further information.
Self-executed function expression
To solve the above problem, we only need to use a large arc to enclose all the code, because the arc () in JavaScript cannot contain statements, therefore, when parsing the function keyword, the parser parses the code into a function expression instead of a function declaration.
Copy codeThe Code is as follows:
// The following two arc () will be executed immediately
(Function () {/* code */} (); // This is recommended.
(Function () {/* code */}) (); // but this is also usable
// Operators such as arc () and JS &, exclusive OR, and comma eliminate ambiguity in function expressions and function declarations.
// Once the parser knows that one of them is an expression, the other is also an expression by default.
// However, pay attention to the content of the next chapter
Var I = function () {return 10 ;}();
True & function () {/* code */}();
0, function () {/* code */}();
// If you do not care about the returned value or are not afraid of reading it
// You can even add a one-dimensional operator before the function.
! Function () {/* code */}();
~ Function () {/* code */}();
-Function () {/* code */}();
+ Function () {/* code */}();
// In another case, the new Keyword can also be used, but I'm not sure about its efficiency.
// Http://twitter.com/kuvos/status/18209252090847232
New function () {/* code */}
New function () {/* code */} () // if you want to pass a parameter, you only need to add an arc ()
The arc mentioned above eliminates ambiguity. In fact, it is not necessary at all, because it is originally expected to be a function expression, but we still use it to facilitate reading by developers, when you assign values to a variable for these automatically executed expressions, we can see that there is an arc at the beginning (and you will soon understand, instead of pulling the code to the end to see if there is any arc.
Save status with closure
Similar to passing parameters when a common function is executed, the self-executed function expression can also pass parameters as well, because the closure can directly reference the passed parameters and use these locked incoming parameters, the self-executed function expression can effectively save the status.
Copy codeThe Code is as follows:
// This code is wrong, because variable I has never carried locked back
// On the contrary, when the loop is executed, we only obtain the value when we click
// At this time, I really get the value
// Therefore, no matter which connection is clicked, I am link #10 will be displayed (if there are 10 a elements)
Var elems = document. getElementsByTagName ('A ');
For (var I = 0; I <elems. length; I ++ ){
Elems [I]. addEventListener ('click', function (e ){
E. preventDefault ();
Alert ('I am link #' + I );
}, 'False ');
}
// This is usable because it is inside the closure of the Self-executed function expression
// The value of I exists as the locked index. After the loop is executed, although the last value of I changes to the total number of a elements (for example, 10)
// But the lockedInIndex value inside the closure is not changed because it has been executed
// When you click Connect, the result is correct.
Var elems = document. getElementsByTagName ('A ');
For (var I = 0; I <elems. length; I ++ ){
(Function (lockedInIndex ){
Elems [I]. addEventListener ('click', function (e ){
E. preventDefault ();
Alert ('I am link #' + lockedInIndex );
}, 'False ');
}) (I );
}
// You can also use the self-executed function expression in the processing function as follows:
// Not outside addEventListener
// But the above Code is more readable.
Var elems = document. getElementsByTagName ('A ');
For (var I = 0; I <elems. length; I ++ ){
Elems [I]. addEventListener ('click', (function (lockedInIndex ){
Return function (e ){
E. preventDefault ();
Alert ('I am link #' + lockedInIndex );
};
}) (I), 'false ');
}
In fact, the lockedInIndex variable in the above two examples can also be changed to I, because it does not work with the external I, so there will be no problem, this is also the power of anonymous functions + closures.
Differences between self-executed anonymous functions and immediate function expressions
In this post, we have been calling Self-execution functions, specifically Self-executing anonymous functions ), however, in the original English text, the author has always suggested using the name of the Function Expression called Immediately (Immediately-Invoked Function Expression). The author has given a bunch of examples to explain it. Well, let's take a look:
Copy codeThe Code is as follows:
// This is a self-executed function. The function executes itself internally and is recursive.
Function foo () {foo ();}
// This is a self-executed anonymous function because the name is not indicated
// You must use the arguments. callee attribute to execute yourself.
Var foo = function () {arguments. callee ();};
// This may also be an self-executed anonymous function. It only indicates that the foo name references itself.
// If you change foo to another one, you will get an anonymous used-to-self-execute function.
Var foo = function () {foo ();};
// Some people call this self-executed anonymous function (even if it is not), because it does not call itself, it is just executed immediately.
(Function () {/* code */}());
// Add a name for the function expression to facilitate debugging
// But it must be named. This function is no longer anonymous.
(Function foo () {/* code */}());
// The function expression (IIFE) that can be called immediately can also be self-executed, but it may not be commonly used.
(Function () {arguments. callee ();}());
(Function foo () {foo ();}());
// In addition, the following code will fail to be executed in BlackBerry 5, because in a named function expression, its name is undefined.
// Haha, strange
(Function foo () {foo ();}());
We hope that some examples here can help you understand what is self-execution and what is immediate call.
Note: arguments. callee has been deprecated in ECMAScript 5 strict mode. Therefore, this mode cannot be used.
Last Narration: Module Mode
When talking about this function expression that is called immediately, I think of the Module mode again. If you are not familiar with this mode, Let's first look at the Code:
Copy codeThe Code is as follows:
// Create an anonymous function expression called immediately
// Return a variable, which contains the things you want to expose
// The returned variable is assigned to counter, instead of the declared function itself.
Var counter = (function (){
Var I = 0;
Return {
Get: function (){
Return I;
},
Set: function (val ){
I = val;
},
Increment: function (){
Return ++ I;
}
};
}());
// Counter is an object with multiple attributes. The code above shows the attributes as a method.
Counter. get (); // 0
Counter. set (3 );
Counter. increment (); // 4
Counter. increment (); // 5
Counter. I; // undefined because I is not an attribute of the returned object
I; // reference error: I is not defined (because I only exists in the closure)
For more information about the Module mode, visit my previous post: Understanding the JavaScript series (2): Fully parsing the Module mode.
Read more
I hope that some examples above will help you understand the expression of the function called immediately (that is, the self-executed function we call). If you want to know