preface

Instant functions are commonly used in third-party libraries to isolate variable scope. Many third-party libraries have a large number of variables and functions. In ES5, the solution to avoid variable contamination is to use instant functions.

In this article, I’m going to share some information about executing functions immediately, and welcome interested developers to read this article.

The concept is introduced

An anonymous function called immediately is also called an immediately called function expression (IIFE). It is similar to a function declaration, but is interpreted as a function expression because it is enclosed in parentheses. The second set of parentheses immediately following the first one calls the preceding function expression, and the code in IIFE is not accessible outside of it.

Let’s take an example:

(function() {
  // block-level scope
  for (var i = 0; i < 5; i++) {
    console.log(i);
  }
})();
console.log(i);

Copy the code

When the above code is parsed to console.log(I); ReferenceError: I is not defined because the variables it accesses are defined internally in IIFE and cannot be accessed externally.

Prior to ES5, IIFE was a very effective way to prevent leakage of variable definitions without causing closure related memory problems because there was no reference to the anonymous function. Therefore, the scope chain of a function can be destroyed as soon as it completes execution.

The full name of IIFE is Immediately Invoked Function Expression, which translates to Immediately invoke Function Expression.

Simulate block-level scopes

Using IIFE, you can simulate block-level scope by declaring variables inside a function expression and then immediately calling the function so that variables in the function body scope are as if they were in the block-level scope (as shown in the example above).

Since ES6, the concept of block-level scope has been added, so we want to achieve the same effect without using IIFE. Let is used to rewrite the above example as follows:

for (let i = 0; i < 5; i++) {
  console.log(i);
}
console.log(i);

Copy the code

For more information on variable scope, please refer to my other article: Understanding scopes and closures in depth

Block-level scopes are no substitute for expressions that call functions immediately, and when your code runs on a browser that doesn’t support ES6+, you have to resort to executing functions immediately to simulate.

Implementing private variables

IIFE can return a function reference, and when the function is executed outside the lexical scope of IIFE, it also creates a closure that enables the function to access local variables.

Let’s take an example, as follows:

const getOrderId = (function() {
  let count = 0;
  return function() {
    ++count;
    return `id_${count}`; }; }) ();console.log(getOrderId());
console.log(getOrderId());
console.log(getOrderId());
console.log(getOrderId());
Copy the code

In the above code:

  • Creates a self-executing function that returns a function reference
  • There is a variable inside the self-executing functioncountIt is a private variable that cannot be accessed externally
  • Finally, return a function reference to form a closure, yescountSince increases with_idConcatenate and return

The count variable inside a function cannot be accessed outside of IIFE, and it cannot be read or written to anywhere other than the function returned from IIFE, thus creating a truly private state variable.

Variable renaming

In normal development, you might encounter two different libraries that expose the same global variable name. For example, if you are using Jquery, the other library also specifies a global variable named $.

To resolve naming conflicts, you can wrap a piece of code in an IIFE, pass a global variable (such as Jquery) as a parameter to the IIFE, and access the value of that parameter with an arbitrary parameter name (such as $) inside the function.

window$=function somethingElse() {

    // Other code

};

 

(function($) {

    // Other code

})(jQuery);
Copy the code

No matter what values are specified in the global scope, these values are “masked” in IIFE. In IIFE, these values are “masked”. The parameter always points to the Jquery method.

Capturing global objects

The global object used by JavaScript code in different environments is different. When the code is running in the browser environment, the global object is Window, but in the Node environment, the global object is Global.

When writing generic JS code, you can use IIFE to wrap it around, for example:

(function(global) {

    // Other code}) (this);
Copy the code

Once wrapped, the value of global is window in the browser environment and Global in the Node environment when used inside IIFE.

Two ways of writing IIFE

The immediate execution function can be written in two ways:

  • (function(){})() Anonymous functions are wrapped in a parenthesis operator followed by a parenthesis
  • (function(){}()) an anonymous function is followed by a parenthesis, and the whole thing is wrapped in a parenthesis operator

The two methods are equivalent. To execute a function immediately, note two things:

  • The function body should be followed by parentheses
  • The function body must be a function expression and not a function declaration

How a function is declared

Before talking about the difference between the two, let’s first understand the two declarations of JS functions: expressions and declarations.

The function is declared as function test(){}, which causes the function to be promoted. All variables declared by the function keyword are compiled by the interpreter first, and can be called regardless of where the declaration is made, but it will not be executed.


test(); / / test
function test() {
  console.log("Test");
}
test(); / / test
Copy the code

Var test = function(){} var test = function(){}

test(); TypeError: test is not a function
var test = function() {
  console.log("Test");
};
Copy the code

The difference between the two

Now, function expressions plus () can be called directly, but a declarative function wrapped in () is considered a function expression by the compiler and can be called directly with (), as in (function test(){})().

Function test(){} {function test(){}} {function test(){}} {function test(){}} {function test(){}} {function test(){}} {function test(){}} Etc., as follows:

function test(){
  console.log("Test"); } ();// error: Unexpected token ')'

+function test() {
  console.log("Test"); } ();// Normal execution

-function test() {
  console.log("Test"); } ();// Normal execution

!function test() {
  console.log("Test"); } ();// Normal execution

~function test() {
  console.log("Test"); } ();// Normal execution

void function test() {
  console.log("Test"); } ();// Normal execution

new function test() {
  console.log("Test"); } ();// Normal execution
Copy the code

Immediate functions are also commonly written as anonymous functions, declaring a function with the function keyword but not giving it a name. Functions declared in this way are anonymous functions, such as function(){}.

Anonymous functions can not be used alone, otherwise js syntax will error, need to be wrapped with (), when we need to pass the value to anonymous functions, the following parentheses can be written, for example:

(function(val) {
  console.log(val); } ("I'm an argument to an anonymous function."));

Copy the code

By the time we get to this point, we’ll see that the code above is written exactly as the second way to write the immediately executed function 😂. We know that the function body is followed by the parentheses, and the function is immediately executed.

We know that self-executing functions need to be wrapped with a (). Previously, we saw that code wrapped with a () is treated as a function expression by the compiler, so it can be immediately called by adding a () after it. You can also pass an anonymous function from the parentheses as follows:

(function(val) {
  console.log(val); }) ("I'm a self-executing anonymous function.");
Copy the code

We find that the above code is written exactly as the first way to write the function immediately 😃

The code address

This article is “JS principle learning” series of the sixth article, the complete route of this series please move: “JS principle learning (1)” learning route planning

For all the sample code in this series, go to jS-learning

Write in the last

At this point, the article is shared.

I’m an amazing programmer, a front-end developer.

If you are interested in me, please visit my personal website for further information.

  • If there are any errors in this article, please correct them in the comments section. If this article helped you, please like it and follow 😊
  • This article was first published in nuggets. Reprint is prohibited without permission 💌