Explain the immediate execution function (function (){}(), (function (){}()

Keywords: Javascript

To know the difference between these kinds of writing, we need to talk a little bit about the other two ways of naming functions in js, that is, expressions and declarations.

The declarative form of a function is: function foo(){/*... */}, which will lead to function promotion. All function keywords will be compiled first by the interpreter. No matter where the declaration is, it can be invoked, but it will not be executed by itself. The definition only lets the interpreter know that it exists, only when it is tuned. It will be executed only when it is used.

Figure 1 Declarative function

The expression of a function is var foo=function(){/* */}, which does not lead to function promotion, so it must be declared before calling, otherwise it will make a mistake, as shown in Figure 2.

Figure 2 Expression Function

Now, back to the main topic, (function (){}(), (function (){}() are two ways to write the immediate execution function in js. The function expression can be directly invoked by adding (), but if the whole declarative function is wrapped up with (), the compiler will think of it as a function expression, so that () can be directly invoked, such as (fu). Ction foo (){/*...*/} (), but if this bracket is added after a declarative function, such as function foo(){/* */} (), it will make an error. Many blogs say that this writing () will be omitted, but it will actually make a mistake, because it does not conform to the JS grammar, so you have to add some symbols to check the grammar of the browser, such as (), +,! And so on, you can see Figure 3 specifically.

Figure 3 Execute the function immediately

 

 

To sum up,

function foo(){console.log("Hello World!")}()//After declaring a function, add()Report wrong
(function foo(){console.log("Hello World!")}())//Wrap the whole expression in parentheses,Normal execution
(function foo(){console.log("Hello World!")})()//Wrap functions in parentheses and execute them properly
!function foo(){console.log("Hello World!")}()//Use! On the contrary, I just want to pass the grammar check here.
+function foo(){console.log("Hello World!")}()//Use+,Normal execution
-function foo(){console.log("Hello World!")}()//Use-,Normal execution
~function foo(){console.log("Hello World!")}()//Use~,Normal execution
void function foo(){console.log("Hello World!")}()//Use void,Normal execution
new function foo(){console.log("Hello World!")}()//Use new,Normal execution

Immediate execution functions are also generally written as anonymous functions. Anonymous functions are written as functions (){/*...*/}, which declare a function using function keywords, but do not name the function. If you need to pass values, you can write parameters directly in parentheses as shown in Figure 4.

Figure 4. Parameters of the immediate execution function

Assigning it to a variable creates functional expressions, assigning an event to an event becomes an event handler, etc. However, it should be noted that anonymous functions can not be used alone, otherwise the js grammar will be wrong, at least wrapped up with (). The above example can be written as follows:

(function(){console.log("I am an anonymous function.")}())
(function(){console.log("I am an anonymous function.")})()
!function(){console.log("I am an anonymous function.")}()
+function(){console.log("I am an anonymous function.")}()
-function(){console.log("I am an anonymous function.")}()
~function(){console.log("I am an anonymous function.")}()
void function(){console.log("I am an anonymous function.")}()
new function(){console.log("I am an anonymous function.")}()

The function of immediate execution is: 1. To create an independent scope, the variables in this scope can not be accessed outside, so that the variable pollution can be avoided. 2. Closures and private data. When it comes to closures, I have to mention the classic closure problem.

 1 <ul id="test">
 2     <li>This is the first one.</li>
 3     <li>This is the second article.</li>
 4     <li>This is Article 3.</li>
 5 </ul>
 6 
 7 <script>
 8     var liList=document.getElementsByTagName('li');
 9     for(var i=0;i<liList.length;i++)
10     {
11         liList[i].onclick=function(){
12             console.log(i);
13         }
14     };
15 </script>

Many people think that if you click on the first li, you will output 1, if you click on the second li, you will output 2, and so on. But the real effect is that no matter how many Li is clicked, it will output 3, as shown in Figure 5. Because i runs through the scope rather than assigning an i to each li, before the onclick event triggered by the user, the for loop is finished, and i=3 when the for loop is finished.

Figure 5 shows how many times you click on the 1st, 2nd, 3li, or click on it again, it will output 3. As you can see, the right console output 8 times 3.

But if we use the immediate execution function to create a separate scope for each li, we can rewrite it as follows, so that we can output several functions by clicking on which item.

 1 <script>
 2     var liList=document.getElementsByTagName('li');
 3     for(var i=0;i<liList.length;i++)
 4     {
 5         (function(ii) {
 6            liList[ii].onclick=function(){
 7                console.log(ii);
 8            }
 9        })(i)
10     };
11 </script>

When the function is executed immediately, the value of i is assigned to ii, and thereafter the value of II remains unchanged, as shown in Figure 6. The value of i changes from 0 to 3, corresponding to three immediate execution functions. The II "respectively" of these three immediate execution functions is 0, 1 and 2.

Figure 6. Click on the number of li to output a few

 

In fact, let in ES6 grammar can also achieve the above functions, just to replace var in for loop with let, as shown below, you feel very simple and clear.

1 <script>
2      var liList=document.getElementsByTagName('li');
3      for(let i=0;i<liList.length;i++)
4      {
5             liList[i].onclick=function(){
6                 console.log(i);
7              }
8      }
9 </script>

Many people think that let can completely replace the immediate execution function. So far, it may be limited by my vision. The immediate execution function I can use can indeed be replaced by let, provided that your operating environment (including old browsers) supports ES2015. If not, you will have to resort to classical functions.

Posted by waiwai933 on Fri, 27 Sep 2019 00:43:32 -0700