【JavaScript专题】--- 当即执行函数表达式

一 什么是当即执行函数表达式

当即执行函数表达式,其实也能够叫初始化函数表达式,英文名:IIFE,immediately-inovked-function expression。当即执行函数表达式就是在定义的时候就当即执行。html

二 当即执行函数表达式的写法

1)写法一express

1 (function (a) {
2   console.log('The result is ' + a);
3 })(5);
4 // The result is 5

2)写法二segmentfault

1 (function (a) {
2   console.log('The result is ' + a);
3 }(5));
4 // The result is 5

三 当即执行函数表达式的特色

1)做用域隔离,避免污染全局的命名空间数组

经过定义一个匿名函数,建立了一个新的函数做用域,至关于建立了一个“私有”的命名空间,该命名空间的变量和方法,不会破坏污染全局的命名空间。若是想传给外部变量或者方法,经过给window上添加对应属性便可。浏览器

例如:Jquery插件就是将window传入,而后给window上添加了$属性。闭包

2)执行完当即销毁ide

执行完后,内部的局部变量和整个函数会被销毁释放掉。函数

1 (function add(a, b) {
2   console.log('The result is ' + (a + b));
3   return a + b;
4 }(5, 3));
5 
6 add(4, 6);
7 
8 // The result is 8
9 // Uncaught ReferenceError: add is not defined

3)当即执行函数表达式不须要带函数名this

若是带了函数名,则被自动忽略。spa

四 当即执行函数表达式的错误写法

下边会针对一些当即执行函数表达式的错误写法,深刻说明其缘由。

要很好的理解下边错误写法的缘由,首先要了解:JavaScript中函数的定义方法;JavaScript中表达式。

1)错误写法一

下边的错误写法的缘由:浏览器解析器遇到function开头的语句,认为这是一个函数定义,但发现该函数没有函数名,致使报错。

1 function () {
2   console.log('The result is 1');
3 }();
4 
5 // Uncaught SyntaxError: Unexpected token (

说明:为何给上边示例代码添加一个圆括号,就能够执行而且不报错了?

这是由于添加圆括号后,就变成表达式。

咱们都知道定义函数有两种方式:

1 // 函数声明:使用function声明函数,并指定函数名
2 function add() {
3   console.log('The result is 1');
4 }
5 
6 // 函数表达式:使用function声明函数,但未指定函数名,将匿名函数赋予一个变量
7 var add = function() {
8   console.log('The result is 1');
9 };

所以当即执行函数表达式,就相似于给函数表达式方式定义的函数,只是在函数定义完添加了圆括号让该函数当即执行了。

根本的缘由仍是将一个函数定义,变成了一个表达式。这也是为何叫当即执行函数表达式的缘由。

让一个匿名函数变成一个表达式的方法不少:

1 !function(){}();
2 +function(){}();
3 -function(){}();
4 ~function(){}();
5 new function(){ /* code */ }
6 new function(){ /* code */ }() // 只有传递参数时,才须要最后那个圆括号。
7 ……

2)错误写法二

1 function add() {
2   console.log('The result is ' + a);
3 }();
4 
5 // Uncaught SyntaxError: Unexpected token )

上边代码会被浏览器解析为以下样子:

1 function add() {
2   console.log('The result is ' + a);
3 };
4 ();

第一个分号前是一个完整的函数定义,没有问题;而第二个分号前的(),出现了语法报错。

注意:当咱们给后边的那个圆括号中添加一个表达式后,就不会报错了。但注意add函数依然不会执行。

 1 function add() {
 2   console.log('The result is 1');
 3 }(2);
 4 
 5 
 6 // 上边等价于下边代码:一部分是函数声明,一部分是执行表达式。所以函数不会执行。
 7 function add() {
 8   console.log('The result is 1');
 9 };
10 (2);

3)错误写法三

当有多个当即执行函数表达式时,必定要带分号:

1 (function () {
2   console.log('this is IIFE 1');
3 }())
4 (function () {
5   console.log('this is IIFE 1');
6 }())
7 
8 // VM80:4 Uncaught TypeError: (intermediate value)(...) is not a function

说明:不带分号会致使JavaScript执行器认为后边括号内容是前边括号内容的参数,而前边括号最终执行结果并非一个函数。而下边代码就不会报错:

 1 (function () {
 2   console.log('this is IIFE 1');
 3   return function(a) {
 4     console.log('this is IIFE 1 return');
 5   }
 6 }())
 7 (function () {
 8   console.log('this is IIFE 2');
 9 }())
10 
11 // this is IIFE 1
12 // this is IIFE 2
13 // this is IIFE 1 return

 五 当即执行函数组成的闭包保存状态

 1 // 这个代码是错误的,由于变量i历来就没背locked住
 2 // 相反,当循环执行之后,咱们在点击的时候i才得到数值
 3 // 由于这个时候i操真正得到值
 4 // 因此说不管点击那个链接,最终显示的都是I am link #10(若是有10个a元素的话)
 5 
 6 var elems = document.getElementsByTagName('a');
 7 
 8 for (var i = 0; i < elems.length; i++) {
 9 
10     elems[i].addEventListener('click', function (e) {
11         e.preventDefault();
12         alert('I am link #' + i);
13     }, 'false');
14 
15 }
16 
17 // 这个是能够用的,由于他在自执行函数表达式闭包内部
18 // i的值做为locked的索引存在,在循环执行结束之后,尽管最后i的值变成了a元素总数(例如10)
19 // 但闭包内部的lockedInIndex值是没有改变,由于他已经执行完毕了
20 // 因此当点击链接的时候,结果是正确的
21 
22 var elems = document.getElementsByTagName('a');
23 
24 for (var i = 0; i < elems.length; i++) {
25 
26     (function (lockedInIndex) {
27 
28         elems[i].addEventListener('click', function (e) {
29             e.preventDefault();
30             alert('I am link #' + lockedInIndex);
31         }, 'false');
32 
33     })(i);
34 
35 }
36 
37 // 你也能够像下面这样应用,在处理函数那里使用自执行函数表达式
38 // 而不是在addEventListener外部
39 // 可是相对来讲,上面的代码更具可读性
40 
41 var elems = document.getElementsByTagName('a');
42 
43 for (var i = 0; i < elems.length; i++) {
44 
45     elems[i].addEventListener('click', (function (lockedInIndex) {
46         return function (e) {
47             e.preventDefault();
48             alert('I am link #' + lockedInIndex);
49         };
50     })(i), 'false');
51 
52 }

 

六 参考资料&内容来源

博客园:https://www.cnblogs.com/tomxu/archive/2011/12/31/2289423.html

SF:http://www.javashuo.com/article/p-pldiqnob-cr.html

百度:https://baijiahao.baidu.com/s?id=1627496475450434415&wfr=spider&for=pc

博客园:http://www.javashuo.com/article/p-pjmyzoku-dk.html

相关文章
相关标签/搜索