This article aims to describe the immediate execution function in detail.

Question origin

In the process of analyzing the Vue source code (Vue2.6.8), I came across such a string of function calls.

template = idToTemplate(template);
Copy the code

The normal logic is to call idToTemplate. Ok, so let’s look at the logic of idToTemplate.

var idToTemplate = cached(function (id) {
      var el = query(id);
      return el && el.innerHTML
    });
Copy the code

Haha, as you can see, idToTemplate is a reference to the result of calling the cached return. Not only that, the cached argument is a function. Let’s take a look at the actual implementation of cached.

function cached(fn) {
  var cache = Object.create(null);
  return (function cachedFn(str) {
    var hit = cache[str];
    return hit || (cache[str] = fn(str))
  })
}
Copy the code

To understand the execution process: Oops! Take a closer look at the () operator, closures, and anonymous function expressions before you can fully understand the process of calling between functions.

Why take functions as arguments?

Why write it this way (function as argument, function as return value)?

To understand this problem, you need to understand the idea behind it: the corrification of functions.

A tricky Question: Why does noop need to be surrounded by ()?

I bring this up here because it has been bothering me for a long time and has not been solved. There must be some thought behind the feeling, because syntax involves only the () operator, function expressions, and a closure if noop returns a function.

Here is the link to the source code.

var generateComponentTrace = (noop); // work around flow check
Copy the code

The first thing I want you to understand is that this is not a matter of executing functions immediately. This should be the problem of work out flow check.

I pushed this question to the community, interested friends can consult.

() operator

The ECMAScript6th specification calls () a group operator.

ParenthesizedExpression : ( Expression )

  1. Return the result of evaluating Expression. This may be of type Reference.

NOTE:

    This algorithm does not apply GetValue to the result of evaluating Expression. The principal motivation for this is so that operators such as delete and typeof may be applied to parenthesized expressions.

() of semantics

Semantic 1, parameter list for function declaration

function func(arg1,arg2){
  // ...
}
Copy the code

Semantics 2, used in conjunction with statements to achieve certain qualifying effects

// This is used with for in
for(var a in obj){
  // ...
}
 
// Use with if
if(boo){
  / /...
}
 
// Use with while
while(boo){
  // ...
}
 
// Use with do while
do{
  // ...
}while(boo)
Copy the code

Semantics 3, used with new to pass values (arguments)

// Suppose we have defined the class Person, which has two fields: name and age.
var p1 = new Person('Jack'.26);
Copy the code

Semantics 4, as a call operator for a function or object method (arguments can also be passed as in semantics 3 if arguments are defined)

// Assume that the function func has been defined
func();
 
// Suppose you have defined the object obj and have func methods
obj.func();
Copy the code

Semantics 5, enforce expression operations

// You're most familiar with using eval to parse JSON
function strToJson(str){
     // string string ();
     var json = eval('(' + str + ') ');
     return json;
}
// Use the anonymous function to execute itself
(function(){
  // ...}) ();Copy the code

closure

Closures are a tricky topic, but once you understand the figure below, you can see that closures are simple.

  • A closure is when an outer function is off the stack and the inner function can still access the variables/attributes of the outer function. The embedded function is called a closure function.
  • Closures fulfill the role of private in Java in the form of syntactic sugar. The idea behind encapsulation is intended to be easy to maintain.

Anonymous function expression

To learn about anonymous function expressions, learn the route: How does a function work? Method: reference specification, multiple debugging. —-> What is the function expression? Method: refer to the specification and test several times. —-> How does the function expression work? Method: multiple debugging.

Let me give you an example. Here is the test code:

<! DOCTYPE html><html>
  <head>
    <title>Create an Instance Example1</title>
    <script src=".. /Vue analysis result.js"></script>
  </head>
  <body>
    <div>idToTemplate call cached</div>
    <script>
      var idToTemplate = cached(function (id) {
        return id
      });
      function cached(fn) {
        var cache = Object.create(null);
        return (function cachedFn(str) {
          var hit = cache[str];
          return hit || (cache[str] = fn(str))
        })
      }
      template = idToTemplate('template');
      console.log(template);
    </script>
  </body>
</html>
Copy the code

Here is the running memory graph (which shows the code running from top to bottom until the end of cached() without calling template = idToTemplate(‘template’); Memory map) :

The figure illustrates the principle of closure phenomena and the principle of anonymous function expression execution.

The function is currified

What is Corrification?

    In mathematics and computer science, currying is the technique of converting a function that takes multiple arguments into a sequence of functions that each takes a single argument. For example, currying a function {\displaystyle f}f that takes three arguments creates three functions:

Aha!!!!! Reading this, it feels more like an idea. Is there a separate data structure designed for Corrification in JS? No.

Arguments? It does, but it’s not going to be an aid to cremation.

So we’re going to implement this idea with existing data structures and say, aha, fancy stuff. It’s like closures. How to do?

This article is very good. It’s easy to understand and I won’t go into details here.