当即执行函数表达式,其实也能够叫初始化函数表达式,英文名: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