在使用for循環的時候,假如需要在循環體中添加一個匿名函數處理其他的事情,那么,在這個匿名函數內,如果需要用到對應的i,因為閉包的緣故,循環體循環結束后才返回i,所以i最終為最后一次++的數值。

?
閉包即函數有權訪問另一函數的局部變量,常用方法為在函數內部創建另一個需要引用這個函數內部變量的函數。
解決方式1

?
通過匿名函數傳參,因為匿名函數取得參數是每次for循環里的i,所以每次打印的值為0,1,2,......
匿名函數自我執行的方法是,在函數體外套一對圓括號,形成一個表達式,在圓括號后再加另一個圓括號,里面可傳參數。此方法即IIFE,又叫立即執行函數表達式。
寫到這里,還需要說一下函數聲明和函數表達式的區別:
1.函數聲明必須有標識符,即函數名;
2.函數聲明存在變量提升;
3.函數聲明不能出現在循環,判斷、try、with等語句的代碼塊中;
解決方式2

此方法和上述方法有異曲同工之妙,也是在匿名函數體外部取到了循環體中的i;
在JS中,每一個函數被調用的時候都會創建一個執行上下文,在該函數內部定義的變量和函數只能在該函數內部被使用,正是因為這個上下文,使得我們在調用函數的時候能創建一些私有變量。
?
為什么a()()兩次打印都是1,是因為每次執行a()()的時候都給a重新賦值1,而b()/c()執行的只是a return出來的匿名函數;

為什么報錯?
因為在javascript解析代碼時,當遇到function關鍵字時,會默認把它當作一個函數聲明,而不是函數表達式,如果沒有顯示的表達成函數表達式,就報錯。因為函數聲明需要一個函數名,而上面的代碼中函數沒有函數名。(在執行到第一個左括號時報錯)

為什么在加了函數名之后,依然報錯?
在一個表達式后面加上括號表示立即執行,而在一個語句后加上括號,該括號和之前的語句完全不搭邊,而只是一個分組操作符,用來控制運算中的優先級,當js解析到括號時,發現里面為空,所以報錯。(在執行到第二個右括號時報錯)
因為在js中括號內部不能為語句,所以js解析到括號時,緊接著發現了function關鍵字,所以自動把括號內的語句當作表達式而不是函數聲明。
所以,立即執行函數,你可以這么寫:

?
而上面我們用立即執行函數加閉包,取到了循環體中的i;可見合理利用立即執行函數加上閉包,還能保存變量的狀態。
在模塊化中,也可以用立即執行函數來處理模塊化,可以減少全局變量造成的空間污染,構造更多的私有變量。
?