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

Time:2019-11-11

To know the difference between these ways of writing, we need to talk about something out of the question – two ways to name functions in JS, that is, expressions and declaratives.

The declarative writing of the function is:function foo(){/*…*/}, this writing method will lead to function promotion. All function keywords will be compiled by the interpreter first. No matter where the declaration is, it can be called, but it will not be executed by itself. The definition only lets the interpreter know its existence, and only when it is called can it be executed.

Fig. 1 declarative function

The expression of the function is written as:var foo=function(){/*…*/}, this writing method will not lead to function promotion, so you mustDeclare before callingOtherwise, an error will occur, as shown in Figure 2.

Figure 2 expression function

Now, to get back to the main point, (function() {} ()), and (function() {} ()) are two kinds of writing methods for immediate function execution in JS. After function expression is added with (), it can be called directly, but if the whole declarative function is wrapped with (), it will be considered as function expression by the compiler, so it can be called directly with (), such as(function foo(){/*…*/})(), but if the parenthesis is appended to a declarative function, such asfunction foo(){/*…*/}()ThenReport errors, many blogs say that this writing method () will be omitted, but it will actually make mistakes. Because it does not conform to the syntax of JS, if you want to pass the syntax check of the browser, you must add some symbols, such as (), +,! And so on. See Figure 3 for details.

Figure 3 immediate execution function

 

 

To summarize:

Function foo() {console. Log ("Hello world!")} () // an error will be reported when a function is declared and followed by ()
(function foo() {console. Log ("Hello world!")} ()) // wrap the whole expression with brackets and execute normally
(function foo() {console. Log ("Hello world!")}) () // wrap the function in parentheses and execute normally
! function foo() {console. Log ("Hello world!")}() // use! , negate. I just want to pass the grammar check here.
+Function foo() {console. Log ("Hello world!")}() // use +, execute normally
-Function foo() {console. Log ("Hello world!")} () // use - to execute normally
~Function foo() {console. Log ("Hello world!")}() // use ~, and execute normally
Void function foo() {console. Log ("Hello world!")}() // use void and execute normally
New function foo() {console. Log ("Hello world!")}() // use new to execute normally

The immediate execution function is generally written as an anonymous function, and the anonymous function is written as function (){/*…*/}, which is to use the function keyword to declare a function without naming the function. If you need to pass values, you can write the parameters directly into brackets as shown in Figure 4.

Figure 4 parameters of immediate execution function

Assign it to a variable and createFunction expression, giving an event becomes an event handler, etc. But it should be noted thatAnonymous function cannot be used alone, otherwise JS syntax error will be reported, at least wrapped with ()。 The above example can be written as follows:

(function() {console. Log ("I'm an anonymous function. } ()
(function() {console. Log ("I'm an anonymous function. (}) ()
! function() {console. Log ("I'm an anonymous function. } ()
+Function() {console. Log ("I'm an anonymous function. } ()
-Function() {console. Log ("I'm an anonymous function. } ()
~Function() {console. Log ("I'm an anonymous function. } ()
Void function() {console. Log ("I'm an anonymous function. } ()
New function() {console. Log ("I'm an anonymous function. } ()

The functions of immediate execution function are as follows: 1. Create an independent scope in which the variables cannot be accessed outside, so as to avoid variable pollution. 2. Closures and private data. When it comes to closures, I have to mention the classic closure problem.

This is the first
     This is the second
     This is number three
 
 
 
     var liList=document.getElementsByTagName('li');
     for(var i=0;i<liList.length;i++)
     {
         liList[i].onclick=function(){
             console.log(i);
         }
     };

Many people think that the execution effect is that clicking the first Li will output 1, clicking the second Li will output 2, and so on. But the real execution effect is that no matter which 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, the for loop is finished before the onclick event triggered by the user, and I = 3 when the for loop is finished.

Figure 5. Click Li 1, Li 2, Li 3 respectively, or click Li again to output 3. It can be seen that the console on the right outputs 3 times

But if we use the immediate execution function to create an independent scope for each Li, we can rewrite it as follows, so that we can achieve the function of clicking the first few items and outputting several.

var liList=document.getElementsByTagName('li');
     for(var i=0;i<liList.length;i++)
     {
         (function(ii) {
            liList[ii].onclick=function(){
                console.log(ii);
            }
        })(i)
     };

When the function is executed immediately, the value of I is assigned to II, and then the value of II remains unchanged, as shown in Figure 6. The value of I changes from 0 to 3, which corresponds to three immediate execution functions. The “II” in the three immediate execution functions is 0, 1 and 2 respectively.

Figure 6 click the number Li to output the number

 

In fact, let in ES6 syntax can also achieve the above functions, just changing VaR in for loop into let, as shown below, which is very simple and clear for you.

var liList=document.getElementsByTagName('li');
      for(let i=0;i<liList.length;i++)
      {
             liList[i].onclick=function(){
                 console.log(i);
              }
      }

So many people think that let can completely replace 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 running environment (including old browsers) supports es2015. If not, you will have to resort to the classic functions of the past.