Deep parsing of immediate execution functions in JavaScript basics

Source: Internet
Author: User
Tags anonymous closure readable

What is it
in JavaScript, each function, when invoked, creates a new execution context. Because variables and functions defined in a function are the only variables that are accessed internally, rather than variables that are accessed externally, when a function is invoked, the context provided by the function provides a very simple way to create a private variable.

function Makecounter () {
  var i = 0;
  return function () {
    console.log (++i);}
  ;

} Remember: ' Counter ' and ' counter2 ' have their own variable ' i '

var counter = Makecounter ();
Counter ();//1
counter ();//2

var counter2 = Makecounter ();
Counter2 ();//1
counter2 ();//2

i;//referenceerror:i is not defined (it only exists in Makecounter)

In many cases, you may not need to makewhatever such a function to return multiple cumulative values, and you can only call one time to get a single value, and in some other cases you don't even need to know exactly what the return value is.

The core of it
now, whether you define a function like this () () () (), or the var foo = function () {}), you need to add a pair of parentheses, such as Foo (), when invoked.

The function defined below can be invoked by adding a pair of parentheses to the function name, such as ' foo () ',
//Because Foo is just a reference variable var foo in relation to the function expression ' function () {/* code * * *

function () {/* code

/}//This can explain that a functional expression can call itself by adding a pair of parentheses afterwards?

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

As you can see, there is a bug caught here. When parentheses appear behind a function in order to invoke a function, whether or not it encounters such a function keyword in the global or local context, the default is to treat it as a function declaration, not a function expression, if you do not explicitly tell the parentheses that it is an expression, It takes it as a function declaration without a name and throws an error because the function declaration requires a name.

Question 1: Here I can think of a question, whether we can also like this directly call the function var foo = function () {Console.log (1)} (), the answer is yes.
Question 2: Similarly, we can think of a problem, what happens when a function declaration such as this one is called directly with parentheses in the back? Please see the answer below.

function, parentheses, error
Interestingly, if you assign a name to a function and put a pair of parentheses behind it, the same will throw the error, but this time for another reason. When parentheses are placed after a function expression indicating that this is a called function, and the parentheses behind a declaration means that it is completely separate from the preceding function declaration, at which point the parentheses are simply a bracket (the parentheses used to control the operation Precedence).

However, the function declaration is syntactically invalid, it is still a declaration, the following parentheses are invalid, because the parentheses need to contain the expression

function foo () {/* Code/} ();//syntaxerror:unexpected token

//Now, you put an expression in parentheses without throwing an error ..., but the function is not executed because: function

foo () {/* Code/} (1)

//It is equivalent to the following A function declaration follows an expression that has no relation at all:

function foo () {/* * Code/}
(1);

Execute function expression now (iife)
Fortunately, correcting grammatical errors is simple. The most popular and accepted method is to enclose the function declaration in parentheses to tell the parser to express a function expression, because in JavaScript, parentheses cannot contain declarations. Because of this, when parentheses run into a function keyword for wrapping functions, it knows to parse it as a function expression instead of a function declaration. Note that the parentheses here and the parentheses above are different when it comes to the function, that is to say.

When parentheses appear at the end of an anonymous function and want to call a function, it defaults to the function declaration as a function.
When parentheses wrap a function, it resolves the function as an expression by default, rather than a function declaration.

Both modes can be used to call a function expression immediately, using the execution of the function to create the private variable (function () {/* Code/} ())//crockford recommends this one, The expression in parentheses represents the function immediate invocation expression (function () {/* Code/}) ();//but this one works just as so, the expression inside the parentheses represents the function expression//Because the point of th e parens or coercing operators is to disambiguate//between function expressions and function declarations, they can/

/omitted when the parser already expects a expression (but please to the//"Important note" below). var i = function () {return 10;}
();
True && function () {/*code*/} ();

0,function () {} ();
If you don't care about the return value, or make your code as readable as possible, you can store the byte!function () {/* Code/} () by taking a unary operator in front of your function.
~function () {/* * Code/} ();
-function () {/* * Code/} ();

+function () {/* * Code/} (); Here's another variation, from @kuvos i ' m not sure to the performance//implications, if any, the ' new ' key
Word, but it works. http://twitter.com/kuvos/status/18209252090847232 new Function () {/* * Code/} new function () {/* * Code/} ()//Only Need parens if passing argumeNts

 

Important Notes about parentheses
in some cases, it is not necessary to surround the function expression with additional ambiguous parentheses (since the parentheses have already expressed it as an expression), but this is still a good idea when the parentheses are used to invoke the function expression.

Such parentheses indicate that the function expression will be called immediately and that the variable will store the result of the function, rather than the function itself. When this is a very long function expression, this saves you the time to read your code without scrolling to the bottom of the page to see if the function is invoked.

As a rule, when you write clearly defined code, it is necessary to prevent JavaScript from throwing errors, and it is also necessary to prevent other developers from throwing errors at you wtferror!

To save the state of a closed package
like when a function is called by their name, the arguments are passed, and the arguments are passed when the function expression is called immediately. A function expression that is called immediately can be used to lock a value and effectively save the state at this time because any function defined in a function can use the arguments and variables passed in by the outer function (this relationship is called a closure).

It may not work as you think, because the value of ' I ' has never been locked.

On the contrary, each link, when clicked (the loop has been executed well), will eject the total number of all elements,//Because this is the true value of ' I ' at this time.
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);
//And rewrite as follows, because in the iife, the ' I ' value is locked in the ' Lockedinindex '.

When the loop finishes executing, although the value of ' I ' values is the sum of all the elements, but every time the function expression is invoked, the ' lockedinindex ' value in//Iife is passed to its value, so the correct value is ejected when the link is clicked.
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 Iife as follows, with only parentheses including the click handler function, not the entire ' addeventlistener '.

Either way, these two examples can be locked with iife, but I find the previous example 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);

 }

Remember, in the last two examples, lockedinindex can access I without any problems, but using a different named identifier as a function parameter can make the concept easier to interpret.

The most significant advantage of immediately executing a function is that even if it is not named or anonymous, a function expression can be called immediately without using an identifier, and a closure can be used without the current variable being contaminated.

What is wrong with performing an anonymous function ("self-executing anonymous function")?

You see it has been mentioned several times, but it is still not so clearly explained, I propose to change the term to "immediately-invoked Function Expression", or, Iife, if you like abbreviations.

What is immediately-invoked Function expression? It causes a function expression to be called immediately. It's like a function expression that guides you to the call.

I think members of the JavaScript community should be able to accept terminology in their articles or statements, immediately-invoked Function expression and iife, because I feel it's easier to get this concept understood, and the term " self-executing anonymous function "is really not accurate enough.

The following is a self executing function that recursively invokes itself

function foo () {foo ();};

This is a self executing anonymous function. Because it does not have an identifier, it must use the ' Arguments.callee ' attribute to invoke its own

var foo = function () {Arguments.callee ();};

This may be considered a self executing anonymous function, but only when the ' foo ' identifier is used as its reference, if you replace it with ' Foo ' to invoke the same viable

var foo = function () {foo ();};

Some people like this are called ' self-executing anonymous function ', even if it's not self executing, because it doesn't call itself. Then it was just called immediately.

(function () {/*code*/} ());

Adding an identifier to a function expression (that is, creating a named function) can be a great help to our debugging. Once named, the function is no longer anonymous.

(function foo () {/* * Code/} ());

Iifes can also be executed, although, perhaps he is not the most useful pattern

(function () {Arguments.callee ();} ())
(function foo () {foo ();} ()

//One last thing to Note:this would cause an error in BlackBerry 5, because
//inside a named function expr Ession, the name is undefined. Awesome, huh?

(function foo () {foo ();} ());

Hopefully the above example will make it clearer to you that the term ' self-executing ' is somewhat misleading because he is not performing his own function, although the function has been executed. Similarly, anonymous functions do not need to be specifically pointed out, because the Immediately invoked function Expression can be either a named function or an anonymous function.

Finally: module mode
when I call a function expression, if I do not remind myself at least once about module mode, I will probably ignore it. If you don't attribute the module pattern in JavaScript, it looks like the following example, but the return value replaces the function with an object.

var counter = (function () {
  var i = 0;
  return {
    get:function () {return
      i;
    },
    Set:function (val) {
      i = val;
    },
    increment: function () {return
      ++i
    }}
  }
  ());
  Counter.get ();//0
  Counter.set (3);
  Counter.increment ();//4
  counter.increment ();//5

  conuter.i;//undefined (' I ' isn't a property of the returned Object)
  i;//referenceerror:i is isn't defined (it only exists inside the closure)

The modular mode method is not only quite powerful but also simple. Very few code, you can effectively use the method and attribute-related naming, in an object, the organization of all the module code that minimizes the global variable pollution also creates the use of variables.

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.