问题引入:咱们写函数,就是为了使咱们的代码更加模块化,而后,提升代码的重用。可是,有些函数,从定义到整个函数就运行了一遍。可是这个函数依然存在,就占用了大量的内存。那有没有一种函数,执行完了以后,就不存在了的呢?面试
什么是匿名函数
声明一个函数,并立刻调用这个匿名函数就叫作当即执行函数;也能够说当即执行函数是一种语法,让你的函数在定义之后当即执行;dom
当即执行函数的建立步骤,看下图:模块化
当即函数形式
接下来看当即执行函数的两种常见形式:函数
//匿名函数包裹在一个括号运算符中,后面跟一个小括号 (function(){ //... })() ////匿名函数后面跟一个小括号,整个包裹在一个括号运算符中 (function(){ //... }())
(),!,+,-,=等运算符都能起到当即执行的做用,这些运算符的做用就是将匿名函数或函数声明转换为函数表达式。spa
要注意两点,一是函数体后面要有小括号(),二是函数体必须是函数表达式而不能是函数声明。code
(function (test) { //使用()运算符,输出123 console.log(test); })(123); (function (test) { //使用()运算符,输出123 console.log(test); }(123)); !function (test) { //使用!运算符,输出123 console.log(test); }(123); var fn = function (test) { //使用=运算符,输出123 console.log(test); }(123);
好处
- 没必要为函数命名,避免了污染全局变量
- 当即执行函数内部造成了一个单独的做用域,能够封装一些外部没法读取的私有变量
- 封装变量
总而言之:当即执行函数会造成一个单独的做用域,咱们能够封装一些临时变量或者局部变量,避免污染全局变量。以一个面试题为例:对象
var liList = ul.getElementsByTagName('li') for(var i=0; i<6; i++){ liList[i].onclick = function(){ alert(i) // 为何 alert 出来的老是 6,而不是 0、一、二、三、四、5 } }
为何 alert 的老是 6 呢,由于 i 是贯穿整个做用域的,而不是给每一个 li 分配了一个 i,以下:blog
划重点:用户必定是在for运行完了以后,才点击的,此时i为6内存
解决方案:作用域
用当即执行函数给每一个li创造一个独立做用域便可(固然还有其余办法):
var liList = ul.getElementsByTagName('li') for(var i=0; i<6; i++){ !function(ii){ liList[ii].onclick = function(){ alert(ii) // 0、一、二、三、四、5 } }(i) }
使用场景
一、你的代码在页面加载完成以后,不得不执行一些设置工做,好比时间处理器,建立对象等等。
二、全部的这些工做只须要执行一次,好比只须要显示一个时间。
三、可是这些代码也须要一些临时的变量,可是初始化过程结束以后,就不再会被用到,若是将这些变量做为全局变量,不是一个好的注意,咱们能够用当即执行函数——去将咱们全部的代码包裹在它的局部做用域中,不会让任何变量泄露成全局变量。看以下代码:
二、全部的这些工做只须要执行一次,好比只须要显示一个时间。
三、可是这些代码也须要一些临时的变量,可是初始化过程结束以后,就不再会被用到,若是将这些变量做为全局变量,不是一个好的注意,咱们能够用当即执行函数——去将咱们全部的代码包裹在它的局部做用域中,不会让任何变量泄露成全局变量。看以下代码:

若是没有被包裹在当即执行函数中,那么临时变量todaydom,days,today,year,month,date,day,msg都将成为全局变量(初始化代码遗留的产物)。用当即执行函数以后,这些变量都不会在全局变量中存在,之后也不会其余地方使用,有效的避免了污染全局变量。