In-depth understanding of JavaScript Series (4): function expression called immediately

Source: Internet
Author: User
Tags closure

This article comes from Uncle Tom

Objective

When you learn JavaScript, you often encounter code that executes anonymous functions, and today we mostly think about self-executing.

Before learning more about this, let's talk about the "self-implementation" of the term, this article is not necessarily the name of the function is not entirely right, mainly to see how the individual understand, because some people say immediately call, some people say automatic execution, so you can completely follow your own understanding to take a name, but I hear a lot of people call it "Self-executing", but the author says a lot later to persuade everyone to call it "function expression called immediately."

This article is the original address: http://benalman.com/news/2010/11/immediately-invoked-function-expression/

What is self-executing?

In JavaScript, any function creates an execution context when it executes, because the variables and function declared for a function are likely to be within that function only, in which context, when calling function, Provides a simple way to create free variables or Private Sub-function.

Since another function is returned in this function, the function can access the free variable i
All say that this internal function actually has permission to invoke an internal object.

function Makecounter () {
I can only be accessed within the 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 (because I is present inside makecounter).

In many cases, we do not need to makecounter multiple instances, or even some cases, we do not need to display the return value, OK, look down.

the heart of the problem

When you declare something like function foo () {} or var foo = functions () {}, you can implement self-execution by appending parentheses to it, such as Foo (), and see the code:

Because I think the function of the first declaration below can be appended with a parenthesis () to execute itself, such as Foo (),
Because Foo is just a reference to the function () {/* code */}-This expression

var foo = function () {/* code */}

// ... Does that mean that the parentheses can be executed automatically after the next one?

function () {/* code */} (); Syntaxerror:unexpected Token (
//

The code above, if even run, the 2nd code error, because when the parser resolves the global function or function internal function keyword, the default is to think of the function declaration, rather than the function expression, if you do not display tell the compiler, It is declared as a function with a missing name by default, and throws a syntax error message because a function declaration requires a name.

Narrator: 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, except for the reasons above. After an expression with parentheses (), the expression executes immediately, but after a statement with parentheses (), it is completely different, and his only grouping operator.

The following function is syntactically fine, but it's still just a statement
Parentheses () will still cause an error, because the grouping operator needs to include an expression

function foo () {/* code */} (); Syntaxerror:unexpected token)

But if you pass an expression in parentheses (), there will be no exception thrown
But the Foo function will still not execute
function foo () {/* code */} (1);


function foo () {/* code */}

(1);

You can access ecma-262-3 in detail. Chapter 5. Functions for further information.

Self-executing function expressions

To solve the problem, it's very simple, we just need to enclose the code in parentheses, because the parentheses () in JavaScript cannot contain statements, so at this point, when the parser parses the function keyword, The corresponding code is parsed into a function expression, not a function declaration.

The following 2 brackets () will be executed immediately

(function () {/* code */} ()); Recommended use of this
(function () {/* code */}) (); But this can be used, too.

Due to the && of brackets () and JS, the XOR, comma, and other operators are ambiguous on function expressions and function declarations.
So once the parser knows that one of them is already an expression, the others are the expressions by default.
However, please note that the following section explains

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 action symbol in front of the function

!function () {/* code */} ();
~function () {/* code */} ();
-function () {/* code */} ();
+function () {/* code */} ();

In another case, using the New keyword can also be used, but I'm not sure how efficient it is
http://twitter.com/kuvos/status/18209252090847232

New function () {/* code */}
New function () {/* code */} ()//If you need to pass parameters, just add parentheses ()

The above-mentioned parenthesis is to eliminate ambiguity, in fact, there is no need, because the parentheses originally expected is 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 the parentheses (, soon to understand Instead of pulling the code to the end to see if there are any parentheses.

save status with closures

As with normal function execution of the time parameters, self-executing functions of the expression can also be such a parameter, because the closure can directly refer to the parameters passed in, using these locked parameters, self-executing function expression can effectively save the state.

This code is wrong, because the variable i has never been back locked live
Instead, when the loop is executed, I get the value when we click
Because this time I do really get the value
So whether 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 is inside the self-executing function expression closure
The value of I is present as an index of locked, and after the loop execution is completed, 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 done it.
So 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 apply a self-executing function expression to a handler function as follows
Not outside of the AddEventListener.
But relatively speaking, 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 above 2 examples of the Lockedinindex variable can also be replaced with I, because and the outside I do not have a role, so there is no problem, which is the power of anonymous function + closure.

self-executing anonymous function and immediately executing function expression differences

In this post, we have been called self-executing functions, specifically self-executing anonymous functions (self-executing anonymous function), but the English original author has always advocated the use of immediately called function expressions (immediately-invoked Function Expression) This name, the author also gave a bunch of examples to explain, OK, let's take a look:

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 indicated
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, only the Foo flag name refers to itself
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 an indication name to the function expression to facilitate debug
But it must be named, and the function is no longer anonymous.
(function foo () {/* code */} ());

Immediately called function expressions (Iife) can also be self-executing, but may not be commonly used
(function () {Arguments.callee ();} ());
(function foo () {foo ();} ());

In addition, the following code executes in BlackBerry 5 with an error, because in a named function expression, his name is undefined
Oh, strange
(function foo () {foo ();} ());

Hopefully here are some examples that can make you understand what is called self-executing and what is called immediate invocation.

Note: Arguments.callee in ECMAScript 5 strict mode is discarded, so in this mode, in fact, is not available.

Final Narration: module mode

When I talk about this immediately called function expression, I think of the module mode, if you are not familiar with this pattern, we first look at the code:

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.

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 way of representing the property.

Counter.get (); 0
Counter.set (3);
Counter.increment (); 4
Counter.increment (); 5

COUNTER.I; Undefined because I is not a property of the returned object
I Reference error: I is not defined (because I only exist in closures)

For more information about module mode, please visit my previous post: In-depth understanding of the JavaScript series (2): Fully parse module mode.

In-depth understanding of JavaScript Series (4): function expression called immediately

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.