In-depth understanding of JavaScript series (4): function expressions called now

Source: Internet
Author: User
Tags mozilla developer network
Preface

When you are learning JavaScript, you often encounter self-executed anonymous functions.CodeToday, 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.

 //  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 (){
// You can only access I in 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:

 //  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 of function () {/* Code */}.

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.

 //  The following function is correct in syntax, but it is still a statement.  
// When brackets () are added, an error is still reported 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 is still not 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.

 //  The following two arc () will be executed immediately.  

( Function (){ /* Code */ }()); // We recommend that you use this
( Function (){ /* Code */ })(); // But this is also usable.

// Since the operators such as arc () and JS &, XOR, and comma eliminate ambiguity in function expressions and function declarations
// So once the parser knows that one of them is already an expression, the other is also the 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 return value, or are not afraid of reading it
// You can even add a one-dimensional operator before a function.

! Function (){ /* Code */ }();
~ Function (){ /* Code */ }();
- Function (){ /* Code */ }();
+ Function (){ /* Code */ }();

// 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 the parameter, you only need to add the 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.

 //  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
// Because at this time, I really get the value
// Therefore, no matter which connection is clicked, I am link #10 is 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 can be used 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 becomes the total number of a elements (for example, 10)
// However, the lockedinindex value inside the closure is not changed because it has already been executed.
// 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 use a self-executed function expression in the processing function as follows:
// Not outside addeventlistener
// However, 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:

 //  This is a self-executed function. The function executes itself internally, recursively  
Function Foo () {Foo ();}

// This is a self-executed anonymous function because no name is 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 just executes it 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:

//  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 the property 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 function expressions that can be called immediately (that is, the self-executed functions we call, for more information about function and module modes, visit the websites listed below:

    1. ECMA-262-3 in detail. Chapter 5. functions.-Dmitry A. soshnikov
    2. Functions and function scope-Mozilla Developer Network
    3. Named function expressions-juriy "kangax" Zaytsev
    4. Full parsing of module mode-Ben cherry (translated by Uncle)
    5. Closures explained with JavaScript-Nick Morgan

 

Transferred from: Uncle Tom

 

Related Article

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.