JavaScript有兩種變量:局部變量和全局變量。前端
局部變量:是指只能在本變量聲明的函數內部調用。web
全局變量:是整個代碼中均可以調用的變量。面試
咱們知道,在JS中變量是須要用var關鍵字聲明的。可是JS中也能夠隱式的使用變量,就是不用聲明,直接使用。並且,千萬注意,JS把隱式聲明的變量老是當成全局變量來使用的。微信
JS中定義在函數內的變量爲局部變量,在函數外部是沒法訪問內部的局部變量的。爲了加深印象,下面再來看一個例子:對象
理解了上面的例子,若是將代碼改成下面這樣,結果又是什麼呢?blog
結果是:JS。由於代碼中的兩個i不同,一個是全局的,一個是局部的,也能夠這樣理解,雖然兩個i的名字同樣,可是這兩個i的本質卻不同,好像有兩個名字同樣的人同樣,雖然名字同樣,但卻不是同一我的。事件
那好,來猜猜下面的結果:圖片
什麼是閉包?普遍的定義就是能訪問局部變量的函數。
閉包就是可以將局部變量延伸到全局來。來看一個例子:
閉包有什麼用?
好比給元素加點擊事件,點擊後獲取該元素的序號。
模擬私有變量、私有屬性。
上面閉包的例子,有個疑問:foo()執行完畢後,變量不就銷燬了嗎?怎麼還能在huhu()中輸出呢?解釋這個疑問,會涉及到數據來源(數據做用域)的問題。閉包裏面涉及到的數據,主要看這個閉包函數是從哪裏來的,也就是這個閉包環境所處的做用域。
仍是上面的例子,閉包環境就是huhu(),不管huhu在哪裏執行,其實huhu函數的內部所掌握的變量就是var fo = 'JS',之因此會這樣是由於Javascript採用詞法做用域,函數的執行依賴於變量做用域,這個做用域是在定義函數時肯定的。所以Javascript中函數對象不只保存代碼邏輯,還必須引用當前的做用域鏈。Javascript中函數內部的局部變量能夠被修改,並且當再次進入到函數內部的時候,上次被修改的狀態仍然持續。這是由於由於局部變量並不保存在棧上,而是經過一個對象來保存。決定使用哪一個變量是由做用域鏈決定的,每次生成函數實例時,都會爲之建立一個「活動對象」用來保存局部變量,而且把這個用於保存局部變量的活動對象加入做用域鏈中。函數實例保存着在執行時所須要的變量的引用,而不會複製保存當時變量的值。
做用域鏈:解析變量時查找變量所在的方式,以var做爲終止符號,若是鏈上一直沒有var,則一直追溯到全局對象爲止。