Objective
When you learn JavaScript, you often encounter the code to execute anonymous functions, today we mainly come to think about the implementation.
Before we get to the details, let's talk about the term "self-execution," this article on the name of this function is not necessarily completely right, mainly to see how the individual understand, because some people say immediately call, and some people say automatic execution, so you can completely according to your own understanding to get a name, but I hear a lot of people call it as "Self-execution", but the author says a lot later to convince everyone to call it "function expression called immediately".
The original English text address: http://benalman.com/news/2010/11/immediately-invoked-function-expression/
What is self-execution?
In JavaScript, any function creates an execution context when it executes, because the variables and function declared for the function are likely to be within the function only, and this context, when the function is invoked, Provides an easy way to create a free variable or a private child function.
Copy Code code as follows:
Because another function is returned in this function, where the function can access the free variable i
All said, this internal function is actually a permission to invoke an internal object.
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, each of which has its own range of I.
var counter = Makecounter ();
Counter (); Logs:1
Counter (); Logs:2
var counter2 = Makecounter ();
Counter2 (); Logs:1
Counter2 (); Logs:2
alert (i); Reference error: I do not have defind (since I is present in the Makecounter interior).
In many cases, we don't need to makecounter multiple instances, and even some cases, we don't need to display the return value, OK, look down.
The core of the problem
When you declare something like function foo () {} or var foo = function () {}, you can implement self execution by adding parentheses in the back, such as Foo (), looking at the code:
Copy Code code as follows:
Because the first function you want to declare below can be followed by a bracket (), such as Foo (),
Because Foo is just a reference to the expression of function () {/* Code/}
var foo = function () {/* code */}
// ... Does that mean that you can do it automatically with parentheses in the back?
function () {/* code */} (); Syntaxerror:unexpected Token (
//
The code above, if even run, 2nd code will be wrong, because when the parser resolves global function or function internal function keyword, the default is to think function declaration, not function expression, if you don't show the compiler, It is declared by default as a function with a missing name, and a syntax error message is thrown because the function declaration requires a name.
Narration: Functions (function), parentheses (paren), syntax error (SYNTAXERROR)
Interestingly, even if you add a name to the wrong code above, he will also prompt for grammatical errors, but not the same reason as above. After an expression is followed by parentheses (), the expression executes immediately, but a statement followed by a parenthesis () is completely different, and his only grouping operator.
Copy Code code as follows:
The following function is grammatically fine, but it's still just a statement
The parentheses () will still be the error, because the grouping operator needs to include an expression
function foo () {/* code */} (); Syntaxerror:unexpected token)
But if you pass an expression in brackets (), there will be no exception thrown
But the Foo function still does not execute
function foo () {/* Code/} (1);
Because it is completely equivalent to the following code, a function declaration is followed by a declaration of an unrelated expression:
function foo () {/* code */}
(1);
You can visit ecma-262-3 in detail. Chapter 5. Functions to get further information.
Self-executing function expression
To solve this problem, it's very simple, we just need to enclose the code in parentheses, because the parentheses in JavaScript cannot contain the statement, so at this point the parser is parsing the function keyword Resolves the corresponding code into a function expression rather than a function declaration.
Copy Code code as follows:
The following 2 brackets () will be executed immediately
(function () {/* code */} ()); Recommended use of this
(function () {/* code */}) (); But this one can also be used.
Because the parentheses () and JS &&, XOR, comma, and other operators are in the function expression and function declaration to eliminate ambiguity
So once the parser knows that one of them is already an expression, the other defaults to the expression.
However, please note that the next section explains the content
var i = function () {return 10;} ();
True && function () {/* code */} ();
0, function () {/* code */} ();
If you don't care about the return value or are not afraid to read
You can even add a unary operation symbol to the function.
!function () {/* * Code/} ();
~function () {/* * Code/} ();
-function () {/* * Code/} ();
+function () {/* * Code/} ();
There's also a situation where you can use the New keyword, but I'm not sure it's efficient
http://twitter.com/kuvos/status/18209252090847232
New function () {/* code */}
The new function () {/* Code/} ()///If you need to pass the argument, just add parentheses ()
The parentheses mentioned above are ambiguous, but there is no need at all. Because the parentheses originally expected the function expression, but we still use it, mainly for the convenience of developers to read, when you let these automatically executed expressions assigned to a variable, we see the beginning of parentheses (, soon we can understand Without having to drag the code to the end to see if there is any parenthesis.
Save state with closure
As with ordinary function execution, the function expression can also be referenced, because the closure can directly refer to the parameters passed in, using these locked incoming parameters, the function expression can save the state effectively.
Copy Code code as follows:
This code is wrong because the variable I never locked live
Instead, when the loop executes, we do not get a numerical value when clicked
Because this time I do get a real value
So whatever you click on that connection, the final display is I am link #10 (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 available because he's inside the closure of the function expression.
The value of I is present as an index of locked, after the end of the loop execution, although the value of the last I becomes the total number of a elements (for example, 10)
But the Lockedinindex value inside the closure is unchanged, because he's already finished.
So when you click on the connection, 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 a self executing function expression in a handler function as follows
And not outside the AddEventListener.
But the above code is relatively 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 above 2 examples of the Lockedinindex variable, can also be replaced by I, because and the outside of I is not a function, so there will be no problem, this is also anonymous function + closure of the power.
The difference between performing an anonymous function and executing the function expression from an immediate
In this post, we have been called the self-executing function, specifically the execution of anonymous functions (the anonymous function), but the English original author has been advocating the use of an immediately called function expression (immediately-invoked Function Expression) This name, the author also cited a bunch of examples to explain, well, let's look at:
Copy Code code as follows:
This is a self executing function that executes itself within the function, recursively
function foo () {foo ();}
This is a self executing anonymous function because no name is marked
You must use the Arguments.callee property to perform your own
var foo = function () {Arguments.callee ();};
This may also be a self executing anonymous function, just the Foo label name referencing its own
If you change Foo to something else, you'll get a used-to-self-execute anonymous function
var foo = function () {foo ();};
Some people call this a self executing anonymous function (even if it's not), because it doesn't call itself, it just executes immediately.
(function () {/* code */} ());
Add a label name to the function expression to facilitate the debug
But it must be named, and this function is no longer anonymous.
(function foo () {/* * Code/} ());
A function expression called immediately (Iife) can also be executed, but it may not be used.
(function () {Arguments.callee ();} ());
(function foo () {foo ();} ());
In addition, the following code executes in the BlackBerry 5 error, because in a named function expression, his name is undefined
Oh, strange
(function foo () {foo ();} ());
I hope some examples here can let you know what is called self execution and what is called immediate invocation.
Note: Arguments.callee is discarded in the ECMAScript 5 strict mode, so in this model, it is actually not available.
Final narration: module mode
When we talk about this immediately called function expression, I think of the module mode, and if you're not familiar with the pattern, let's look at the code first:
Copy Code code as follows:
Create an anonymous function expression that is called immediately
Return a variable in which the variable contains what you want to expose.
The returned variable will be assigned to counter, not the function itself declared outside the
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, and the above code is actually a method for representing the attributes
Counter.get (); 0
Counter.set (3);
Counter.increment (); 4
Counter.increment (); 5
COUNTER.I; Undefined because I am not a property of the return object
I Reference error: I is not defined (because I exist only in closures)
For more information on module mode, please visit my previous post: Deep understanding of the JavaScript series (2): Fully parse module mode.
Read more
Hopefully, some of the above examples will give you an idea of the immediate function expression (which is what we call the self execution function), and if you want to learn more about function and module mode, continue to visit the Web sites listed below:
- Ecma-262-3 in detail. Chapter 5. Functions. -Dmitry A. Soshnikov
- Functions and function Scope-mozilla Developer Network
- Named function Expressions-juriy "Kangax" Zaytsev
- Comprehensive parsing module mode-Ben Cherry (Uncle Translator)
- Closures explained with Javascript-nick Morgan