Home > Web Front-end > JS Tutorial > In-depth understanding of JavaScript series (4) Immediately called function expression_javascript skills

In-depth understanding of JavaScript series (4) Immediately called function expression_javascript skills

WBOY
Release: 2016-05-16 17:57:08
Original
928 people have browsed it

Preface
When you learn JavaScript, you often encounter code for self-executing anonymous functions. Today we will mainly talk about self-execution.
Before we learn more about this, let’s talk about the name “self-execution”. The name of this function in this article may not be completely correct. It mainly depends on how individuals understand it, because some people say that it is called immediately. Some people say automatic execution, so you can choose a name according to your own understanding. However, I heard many people call it "self-execution", but the author said a lot later to convince everyone to call it "immediate call". function expression".
The original English address of this article: http://benalman.com/news/2010/11/immediately-invoked-function-expression/
What is self-execution?
In JavaScript, any function will create an execution context when it is executed, because the variables and functions declared for the function may only be inside the function. This context provides a simple way when calling the function. way to create free variables or private subfunctions.

Copy code The code is as follows:

// Since this function returns another function, Among them, this function can access the free variable i
// All said, this internal function actually has permission to call the internal object.
function makeCounter() {
// i can only be accessed inside makeCounter
var i = 0;
return function () {
console.log( i);
} ;
}
// Note that counter and counter2 are different instances, each with i in its own range.
var counter = makeCounter();
counter(); // logs: 1
counter(); // logs: 2
var counter2 = makeCounter();
counter2() ; // logs: 1
counter2(); // logs: 2
alert(i); // Reference error: i is not defind (because i exists inside makeCounter).

In many cases, we don’t need multiple instances of makeCounter, and even in some cases, we don’t need to display the return value. OK, look down.

The core of the problem
When you declare a function like function foo(){} or var foo = function(){}, you can achieve self-execution by adding parentheses at the end, such as foo( ), look at the code:
Copy the code The code is as follows:

// Because I want the first one below A declared function can be executed by itself by adding a bracket () after it, such as foo(),
// because foo is just a reference to the expression function() { /* code */ }
var foo = function(){ /* code */ }
// ...Does it mean that even if you add parentheses at the end, it can be executed automatically?
function(){ /* code */ }(); // SyntaxError: Unexpected token (
//

The above code, if even run, the 2nd code will error , because when the parser parses the global function or function internal function keyword, it defaults to a function declaration instead of a function expression. If you do not explicitly tell the compiler, it will default to a function that lacks a name, and Throws a syntax error message because the function declaration requires a name.
Aside: function, parentheses, syntaxError (SyntaxError)
Interestingly, even if you add The previous name will also prompt a syntax error, but the reason is different from the above. If you add parentheses () after an expression, the expression will be executed immediately, but if you add parentheses () after a statement, it will be executed immediately. The meaning is completely different, his is just the grouping operator
Copy code The code is as follows: >// The following function is grammatically correct, but it is still just a statement // After adding parentheses (), an error will still be reported, because the grouping operator needs to contain the expression function foo(){ /* code */ }(); // SyntaxError: Unexpected token )
// But if you pass an expression in brackets (), no exception will be thrown
// But the foo function
function foo(){ /* code */ }( 1 );
// is still not executed because it is completely equivalent to the following code. After a function declaration, an unrelated one is declared. Expression:
function foo(){ /* code */ }
( 1 );


You can visit ECMA-262-3 in detail. Chapter 5. Functions for further information.
Self-executing function expression
To solve the above problem, it is very simple. We only need to use curly brackets to enclose all the code. Because statements cannot be included in brackets () in JavaScript, so at this point When parsing the function keyword, the parser will parse the corresponding code into a function expression instead of a function declaration.
Copy code The code is as follows:

// The following 2 brackets () will be executed immediately
(function () { /* code */ } ()); // It is recommended to use this
(function () { /* code */ })(); // But this can also be used
// Since brackets () and JS’s &&, XOR, comma and other operators disambiguate function expressions and function declarations
// so once the parser knows that one of them is already an expression, the other are all expressions by default
// However, please pay attention to the content explanation in the next chapter
var i = function () { return 10; } ();
true && function () { /* code */ } ();
0, function () { /* code */ } ();
// If you don’t care about the return value, or are not afraid of being difficult to read
// you can even You can add the unary operation symbol
!function () { /* code */ } ();
~function () { /* code */ } ();
-function () { /* code */ } ();
function () { /* code */ } ();
// There is another case, using the new keyword, it can also be used, but I am not sure about it Efficiency
// http://twitter.com/kuvos/status/18209252090847232
new function () { /* code */ }
new function () { /* code */ } () / / If you need to pass parameters, you only need to add parentheses ()

The parentheses mentioned above are for disambiguation. In fact, they are not necessary at all, because the parentheses are originally expected to be function expressions. But we still use it, mainly to make it easier for developers to read. When you assign these automatically executed expressions to a variable, we see brackets (() at the beginning, which can be understood quickly without the need to Scroll to the end to see if there are parentheses.
Use a closure to save the state.
Just like passing parameters when executing a normal function, self-executing function expressions can also pass parameters in this way, because closures can be referenced directly. With these parameters passed in, self-executing function expressions can effectively save state by using these locked incoming parameters.
Copy code The code is as follows:

// This code is wrong because the variable i never It’s not locked
// On the contrary, after the loop is executed, i only gets the value when we click
// Because at this time i really gets the value
// So no matter which connection is clicked , the final displayed ones are I am link #10 (if there are 10 a elements)
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');
}
// This can be used because it is inside the self-executing function expression closure
// The value of i exists as the locked index and is executed in the loop After the end, although the value of i finally becomes the total number of elements in a (for example, 10)
// the lockedInIndex value inside the closure has not changed because it has been executed
// so when you click the connection time, the result is correct
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 apply it as follows, using the self-executing function expression in the handler function
// instead of outside addEventListener
// But relatively speaking, the above code is 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');
}

In fact, the lockedInIndex variable in the above two examples can also be replaced by i. Because it does not act on the same function as the external i, there will be no problem. This is also the power of anonymous function closures.
The difference between a self-executing anonymous function and an immediately executed function expression
In this post, we have always called it a self-executing function, to be precise, it is a self-executing anonymous function (Self-executing anonymous function), but the original English text The author has always advocated the use of the name Immediately-Invoked Function Expression. The author also gave a bunch of examples to explain, okay, let's take a look:
Copy code The code is as follows:

// This is a self-executing function, the function executes itself internally, recursively
function foo() { foo(); }
// This is a self-executing anonymous function because there is no marked name
// You must use the arguments.callee attribute to execute itself
var foo = function () { arguments. callee(); };
// This may also be a self-executing anonymous function, just the foo tag name refers to itself
// If you change foo to something else, you will get a used-to -self-execute anonymous function
var foo = function () { foo(); };
// Some people call this a self-executing anonymous function (even if it is not), because it does not call itself, it Just execute it immediately.
(function () { /* code */ } ());
// Adding a label name to the function expression can facilitate debugging
// But it must be named, and the function will no longer It is anonymous
(function foo() { /* code */ } ());
// Immediately invoked function expression (IIFE) can also be self-executed, but it may not be commonly used
(function () { arguments.callee(); } ());
(function foo() { foo(); } ());
// In addition, the following code will execute on BlackBerry 5 Error, because in a named function expression, his name is undefined
// Haha, strange
(function foo() { foo(); } ());

I hope that some examples here can help everyone understand what self-execution is and what immediate calling is.
Note: arguments.callee is obsolete in ECMAScript 5 strict mode, so it cannot be used in this mode.

Final narration: Module mode
When talking about this immediately called function expression, I remembered the Module mode again. If you are not familiar with this mode, let’s take a look at the code first. :
Copy code The code is as follows:

// Create an anonymous function expression that is called immediately
// Return a variable, which contains what you want to expose
// The returned variable will be assigned to counter, not the function itself declared outside
var counter = (function () {
var i = 0;
return {
get: function () {
return i;
},
set: function (val) {
i = val ;
},
increment: function () {
return i;
}
};
} ());
// counter is a variable with multiple The object of the attribute. The above code actually reflects the attribute as the method
counter.get(); // 0
counter.set(3);
counter.increment(); // 4
counter.increment(); // 5
counter.i; // undefined because i is not a property of the returned object
i; // Reference error: i is not defined (because i only exists in closures)

For more introduction to the Module pattern, please visit my previous post: In-depth Understanding of JavaScript Series (2): Comprehensive Analysis of the Module Pattern.
More Reading
I hope that some of the above examples can give you an understanding of the expression of functions that are called immediately (that is, what we call self-executing functions). If you want to know more about the function and Module patterns For information, please continue to visit the websites listed below:
  1. ECMA-262-3 in detail. Chapter 5. Functions. - Dmitry A. Soshnikov
  2. Functions and function scope - Mozilla Developer Network
  3. Named function expressions - Juriy “kangax” Zaytsev
  4. Comprehensive analysis of Module mode- Ben Cherry (translated and edited by uncle)
  5. Closures explained with JavaScript - Nick Morgan
Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template