本節書摘來自異步社群《深入了解javascript》一書中的第1章,第1.13節,作者: 【美】axelrauschmayer(羅徹麥爾)譯者: 王玉林 , 杜歡 , 莊婷婷 , 章子鵬,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。
在javascript中,通過在變量前使用var語句聲明變量:

你可以使用單個var語句聲明和初始化多個變量:
但是我推薦使用單獨聲明每一個變量(原因參考26.4.1“文法”)。是以,我會将之前的語句重寫為:
由于前置的緣故(參考1.13.2“變量的提升特性”),通常它的最佳實踐是在一個函數的開始部分聲明變量。
1.13.1 變量是函數作用域的
一個變量的作用域總是完整的函數(相對于目前塊)。例如:
我們可以看到變量tmp并不局限于(1)行;直到函數結束它都存在。
1.13.2 變量的提升特性
所有變量聲明都會被提升:聲明會被移動到函數的開始處,而指派則仍然會在原來的位置進行。例如,以下函數中的變量會被認為是在标記為(1)的這行聲明的:
然而在程式内部,上述函數的執行過程其實是這樣的:
1.13.3 閉包
每個函數都和它周圍的變量保持着連接配接,哪怕它離開被建立時的作用域也是如此。例如:
函數從标記為(1)的這行開始被建立,在建立結束後即離開它的上下文環境,但它仍然保持着和start的連接配接:
函數以及它所連接配接的周圍作用域中的變量即為閉包。是以,create incrementor()的傳回其實就是一個閉包。
1.13.4 iife模式:引入一個新的作用域
有時你會想要引入一個新的作用域,例如,防止一個變量變成全局變量。在javascript中,不能通過塊來做,必須使用函數。不過有一種模式可以将函數當做類似塊的方式來使用。這種模式被稱作為iife(立即調用函數表達式,發音為“iffy”):
請務必鍵入以上示例(注釋除外)。iife是一個在定義之後就被立即調用的函數表達式。在函數内部,會有一個新的作用域,以防止tmp變成全局變量。更多關于iife的細節,參見16.6“通過iife引入新的作用域”。
iife用例:閉包造成的無意共享
閉包會持續地保持與外部變量的連接配接,而這有時候并不是你想要的:
标記為(1)的這行傳回值總是i的目前值,而并非函數被建立時的值。在循環結束之後,i的值為5,是以數組中所有的函數都傳回這個數值。如果你想要标記(1)這行的函數獲得目前i值的一個快照,那麼你可以使用iife: