Home  >  Article  >  Web Front-end  >  Detailed answer to immediate execution function in JavaScript

Detailed answer to immediate execution function in JavaScript

亚连
亚连Original
2018-05-21 12:01:33945browse

The immediate execution function mode in JavaScript allows your function to be executed immediately after being defined. Let’s deeply analyze the immediate execution function in JavaScript. Friends who need it can refer to it

What is itIn JavaScript, every function, when called, creates a new execution context. Because variables defined within functions and functions are the only variables that are accessed internally, rather than externally, the context provided by the function provides a very simple way to create private variables when the function is called.

function makeCounter() {
  var i = 0;
  return function(){
    console.log(++i);
  };  
}

//记住:`counter`和`counter2`都有他们自己的变量 `i`

var counter = makeCounter();
counter();//1
counter();//2

var counter2 = makeCounter();
counter2();//1
counter2();//2

i;//ReferenceError: i is not defined(它只存在于makeCounter里)

In many cases, you may not need a function like makeWhatever to return multiple accumulated values, and can only call it once to get a single value. In other cases, you do not even need to explicitly Know the return value.

The core of itNow, whether you define a function like this function foo(){} or var foo = function(){}, when calling, you need to add A pair of parentheses, like foo().

//向下面这样定义的函数可以通过在函数名后加一对括号进行调用,像这样`foo()`,
//因为foo相对于函数表达式`function(){/* code */}`只是一个引用变量

var foo = function(){/* code */}

//那这可以说明函数表达式可以通过在其后加上一对括号自己调用自己吗?

function(){ /* code */}(); //SyntaxError: Unexpected token (

As you can see, an error was caught here. When parentheses appear after a function for calling a function, whether it encounters such a function keyword in the global environment or the local environment, by default, it will treat it as a function declaration rather than a function expression. If you If you don't explicitly tell the parentheses that it is an expression, it will treat it as a function declaration without a name and throw an error, since function declarations require a name.

Question 1: Can we think about a question here, can we also directly call the function like this var foo = function(){console.log(1)}(), the answer is yes.
Question 2: Similarly, we can also think about a question. If a function declaration like this is directly called with parentheses at the end, what will happen? Please see the answer below.

Functions, parentheses, errorsInterestingly, if you specify a name for a function and put a pair of parentheses after it, the same error will be thrown, but this This time it was for another reason. When parentheses are placed after a function expression, it indicates that this is a called function, and when parentheses are placed after a declaration, it means that it is completely separated from the previous function declaration. At this time, the parentheses are just a simple representation. A parentheses (parentheses used to control the precedence of operations).

//然而函数声明语法上是无效的,它仍然是一个声明,紧跟着的圆括号是无效的,因为圆括号里需要包含表达式

function foo(){ /* code */ }();//SyntaxError: Unexpected token

//现在,你把一个表达式放在圆括号里,没有抛出错误...,但是函数也并没有执行,因为:

function foo(){/* code */}(1)

//它等同于如下,一个函数声明跟着一个完全没有关系的表达式:

function foo(){/* code */}
(1);

Immediately executed function expression (IIFE) Fortunately, fixing syntax errors is easy. The most popular and accepted method is to wrap a function declaration in parentheses to tell the parser to express a function expression, because in JavaScript, parentheses cannot contain declarations. Because of this, when parentheses enclose a function and encounter the function keyword, it knows to parse it as a function expression rather than a function declaration. Note that the parentheses here behave differently than the parentheses above when they encounter functions, that is to say.

When parentheses appear at the end of an anonymous function and you want to call the function, it will default to the function as a function declaration.
When parentheses wrap a function, it will default to parsing the function as an expression instead of a function declaration.

//这两种模式都可以被用来立即调用一个函数表达式,利用函数的执行来创造私有变量

(function(){/* code */}());//Crockford recommends this one,括号内的表达式代表函数立即调用表达式
(function(){/* code */})();//But this one works just as well,括号内的表达式代表函数表达式

// Because the point of the parens or coercing operators is to disambiguate
// between function expressions and function declarations, they can be
// omitted when the parser already expects an expression (but please see the
// "important note" below).

var i = function(){return 10;}();
true && function(){/*code*/}();
0,function(){}();

//如果你并不关心返回值,或者让你的代码尽可能的易读,你可以通过在你的函数前面带上一个一元操作符来存储字节

!function(){/* code */}();
~function(){/* code */}();
-function(){/* code */}();
+function(){/* code */}();

// Here's another variation, from @kuvos - I'm not sure of the performance
// implications, if any, of using the `new` keyword, but it works.
// http://twitter.com/kuvos/status/18209252090847232

new function(){ /* code */ }
new function(){ /* code */ }() // Only need parens if passing arguments

Important notes about parenthesesIn some cases, additional ambiguous parentheses around a function expression are not necessary (because the parentheses at this time have already separated it. as an expression), but it's still a good idea when parentheses are used to call function expressions.

Such brackets indicate that the function expression will be called immediately, and the variable will store the result of the function, not the function itself. When this is a very long function expression, this can save a person reading your code time from having to scroll to the bottom of the page to see if the function is called.

As a rule, when you write clear and concise code, it is necessary to prevent JavaScript from throwing errors, and it is also necessary to prevent other developers from throwing errors WTFError!

Preserving the state of a closure Just as arguments are passed when a function is called by their name, arguments are also passed when a function expression is called immediately. An immediately called function expression can be used to lock the value and effectively save the current state, because any function defined within a function can use the parameters and variables passed in by the outer function (this relationship is called a closure) .

// 它的运行原理可能并不像你想的那样,因为`i`的值从来没有被锁定。
// 相反的,每个链接,当被点击时(循环已经被很好的执行完毕),因此会弹出所有元素的总数,
// 因为这是 `i` 此时的真实值。

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);
}

// 而像下面这样改写,便可以了,因为在IIFE里,`i`值被锁定在了`lockedInIndex`里。
// 在循环结束执行时,尽管`i`值的数值是所有元素的总和,但每一次函数表达式被调用时,
// IIFE 里的 `lockedInIndex` 值都是`i`传给它的值,所以当链接被点击时,正确的值被弹出。

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);
}

//你同样可以像下面这样使用IIFE,仅仅只用括号包括点击处理函数,并不包含整个`addEventListener`。
//无论用哪种方式,这两个例子都可以用IIFE将值锁定,不过我发现前面一个例子更可读

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);
  }

Remember, in these last two examples, lockedInIndex can access i without any problems, but using a different named identifier as the function parameter can make the concept easier to explain.

One of the most significant advantages of executing a function immediately is that even if it is unnamed or anonymous, a function expression can be called immediately without an identifier, and a closure can be called immediately without a current variable. contamination is used.

What are the problems with self-executing anonymous function ("Self-executing anonymous function")?

你看到它已经被提到好几次了,但是它仍然不是那么清楚的被解释,我提议将术语改成"Immediately-Invoked Function Expression",或者,IIFE,如果你喜欢缩写的话。

什么是Immediately-Invoked Function Expression呢?它使一个被立即调用的函数表达式。就像引导你去调用的函数表达式。

我想Javascript社区的成员应该可以在他们的文章里或者陈述里接受术语,Immediately-Invoked Function Expression和 IIFE,因为我感觉这样更容易让这个概念被理解,并且术语"self-executing anonymous function"真的也不够精确。

//下面是个自执行函数,递归的调用自己本身

function foo(){foo();};

//这是一个自执行匿名函数。因为它没有标识符,它必须是使用`arguments.callee`属性来调用它自己

var foo = function(){arguments.callee();};

//这也许算是一个自执行匿名函数,但是仅仅当`foo`标识符作为它的引用时,如果你将它换成用`foo`来调用同样可行

var foo = function(){foo();};

//有些人像这样叫'self-executing anonymous function'下面的函数,即使它不是自执行的,因为它并没有调用它自己。然后,它只是被立即调用了而已。

(function(){ /*code*/ }());

//为函数表达式增加标识符(也就是说创造一个命名函数)对我们的调试会有很大帮助。一旦命名,函数将不再匿名。

(function foo(){/* code */}());

//IIFEs同样也可以自执行,尽管,也许他不是最有用的模式

(function(){arguments.callee();}())
(function foo(){foo();}())

// One last thing to note: this will cause an error in BlackBerry 5, because
// inside a named function expression, that name is undefined. Awesome, huh?

(function foo(){ foo(); }());

希望上面的例子可以让你更加清楚的知道术语'self-executing'是有一些误导的,因为他并不是执行自己的函数,尽管函数已经被执行。同样的,匿名函数也没用必要特别指出,因为,Immediately Invoked Function Expression,既可以是命名函数也可以匿名函数。

最后:模块模式当我调用函数表达式时,如果我不至少一次的提醒我自己关于模块模式,我便很可能会忽略它。如果你并不属性 JavaScript 里的模块模式,它和我下面的例子很像,但是返回值用对象代替了函数。

var counter = (function(){
  var i = 0;
  return {
    get: function(){
      return i;
    },
    set: function(val){
      i = val;
    },
    increment: function(){
      return ++i;
    }
  }
  }());
  counter.get();//0
  counter.set(3);
  counter.increment();//4
  counter.increment();//5

  conuter.i;//undefined (`i` is not a property of the returned object)
  i;//ReferenceError: i is not defined (it only exists inside the closure)

模块模式方法不仅相当的厉害而且简单。非常少的代码,你可以有效的利用与方法和属性相关的命名,在一个对象里,组织全部的模块代码即最小化了全局变量的污染也创造了使用变量。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

JavaScript中各数制转换全面总结(图文教程)

原生JavaScript来实现对dom元素class的操作方法(图文教程)

JavaScript中的字符串连接问题(图文教程)

The above is the detailed content of Detailed answer to immediate execution function in JavaScript. For more information, please follow other related articles on the PHP Chinese website!

Statement:
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