爲了隱藏內部實現,能夠經過在任意代碼片斷外部添加包裝函數,可是這並不理想,由於必須聲明一個具名函數,意味着這個函數名稱自己會污染函數所在的做用域;同時必須經過顯式地調用函數才能運行其中的代碼。函數
*:區分函數聲明和表達式最簡單的方法是看function關鍵字出如今聲明中的位置。若是function是聲明中的第一個詞,那麼就是一個函數聲明,不然就是一個函數表達式。code
JS提供了同時解決這兩個問題的方案:作用域
var a=2; (function foo(){ var a=3; console.log(a);//3 })(); console.log(a);//2
以上這種模式稱爲當即執行函數表達式(IIFE)。io
有一個改進的形式:console
var a=2; (function foo(){ var a=3; console.log(a);//3 }());//調用的括號包含在用來包裝的()裏 console.log(a);//2
兩種形式在功能上是一致的。function
IIFE有一個進階用法:把它們看成函數調用並傳遞參數進去。進階
var a=2; (function IIFE(global){ var a=3; console.log(a);//3 console.log(global.a);//2 })(window); console.log(a);//2
IIFE還有一種變化的用途是倒置代碼的運行順序,將須要運行的函數放在第二位。循環
var a=2; (function IIFE(def){ def(window); })(funtion def(global){ var a=3; console.log(a);//3 console.log(global.a);//2 })
只要聲明是有效的,在聲明中的任意位置均可以使用{...}括號來爲let建立一個用於綁定的塊。方法
var foo=true; if(foo){ {//顯式的塊 let bar=foo*2; console.log(bar);//2 } console.log(bar);//ReferenceError } console.log(bar);//ReferenceError
**:let循環:for的循環頭部使用let,不只將i綁定到for的塊中,事實上它將其從新綁定到了循環的每一個迭代中,確保使用上一個循環迭代結束時的值從新進行賦值。co
*:塊做用域不該該徹底做爲函數做用域的替代方案,兩種功能應該同時存在。