淺談JS中var、let、const變量定義的不同之處。

在JS開發中,有三種變量定義方式:var、let、const,他們是有很大區別的!

用var來聲明變量會出現的問題:

  • 1. 允許重複的變量聲明:導致數據被覆蓋;
  • 2. 變量提升:怪異的數據訪問、閉包問題;
  • 3. 全局變量掛載到全局對象:全局對象成員汙染問題;

例1:

淺談JS中var、let、const變量定義的不同之處。

淺談JS中var、let、const變量定義的不同之處。

用var聲明的變量會默認被提升到當前作用域的頂部

例2:

淺談JS中var、let、const變量定義的不同之處。

淺談JS中var、let、const變量定義的不同之處。

For循環內的i變量當前所處的環境是全局作用域(函數局部作用域同理,只不過聲明之後不綁定在window上)。

所以在最後點擊事件觸發的時候打印的i都是當前作用域上的同一個i,也即是最後的11

,這就產生了閉包,如下圖:

淺談JS中var、let、const變量定義的不同之處。

ES6 中引入let 和 const,以及塊級作用域來解決這個問題

什麼是塊級作用域

塊級作用域:代碼執行時遇到花括號,會創建一個塊級作用域,花括號結束,銷燬塊級作用域

let在全局作用域下定義變量不會掛在到頂層對象window上

let聲明的變量,不允許當前作用域範圍內重複聲明,在塊級作用域中用let定義的變量,在作用域外不能訪問

let不會有變量提升,因此,不能在定義let變量之前使用它

例1(對比):

淺談JS中var、let、const變量定義的不同之處。

淺談JS中var、let、const變量定義的不同之處。

為什麼會出現error,因為在let和const中引入了一個暫存該類變量的區域Temporal Dead Zone,簡稱TDZ。就是我們所說的臨時死區。

在TDZ中的變量不能被訪問,不然就會報錯,只有在給該變量賦值的時候才會從死區內接觸。

問題:let和const申明的變量真的不被提升嗎?

let聲明的變量實際上也會有提升,但是,提升後會將其放入到“暫時性死區”,如果訪問的變量位於暫時性死區,則會報錯:“Cannot access 'a' before initialization”。當代碼運行到該變量的聲明語句時,會將其從暫時性死區中移除。

例2(對比):

淺談JS中var、let、const變量定義的不同之處。

淺談JS中var、let、const變量定義的不同之處。

輕鬆解決閉包問題

但是我們看到,此時for循環內()中的let i並不在塊級作用域內,講道理應該最後點擊時,打印的應該是這個全局上的i。這個i最後是11,可是從結果上來看卻不是這樣。

在全局上打印這個i:

淺談JS中var、let、const變量定義的不同之處。

淺談JS中var、let、const變量定義的不同之處。

說明這個for循環()內的i並不是定義在全局作用域上的:

原因:

對於for循環()內let定義的變量,做了特殊的處理。此變量相當於默認聲明在後面塊級作用域內

const

const 和let特性相同,唯一不同的是,const一般指的都是常量,常量的定義是不可改變的變量,所以用const 申明的變量是不可變的,且只能在定義是進行賦值。

值得注意的是const聲明的常量是指存入內存的內存空間不可變。這也就意味著,如果存的是引用值,改變引用值內的屬性,const所對應的值就會改變。

淺談JS中var、let、const變量定義的不同之處。

通常在開發中能寫const就用const,不行就用let,這樣出bug率小。


分享到:


相關文章: