ES6建議不再使用var
定義變量,而使用let
定義變量颈娜,const
定義常量剑逃。
無論是
let
還是const
,它們均解決了JS中長久以來的變量定義的問題浙宜。
咱們先聊聊var
和let
的區(qū)別。
一蛹磺、變量具有塊級作用域粟瞬,在代碼塊之外不可使用
使用var
定義變量時,無論其實際聲明位置在何處萤捆,都會被視為聲明于所在函數(shù)的頂部 (如果聲明不在任意函數(shù)內裙品,則視為在全局作用域的頂部),使用if或者for等循環(huán)定義的變量俗或,變量同樣會被提升到if或for所在的函數(shù)頂部市怎。
使用let
定義變量時,該變量只能在當前塊級作用域里使用辛慰,在外部訪問會顯示未定義
塊級作用域(又被稱為詞法作用域)會在以下兩種情況被創(chuàng)建:
- 在一個函數(shù)內部
- 在一個代碼塊(由一對花括號包裹,比如if区匠、for、switch帅腌、while)內部
接下來我們看看在循環(huán)中使用的情況
如果我們在for循環(huán)中用var
定義變量驰弄,在延遲后輸出i
,可以看到全部輸出的都是3速客,這是由于i
變量的定義被提升出去了戚篙,左邊的代碼等價于右邊的代碼
而在過去我們要解決這個問題只能通過 IIFE 來強制改變作用域去解決這個問題
如果在for循環(huán)中使用let
定義變量,變量所在的作用域是在循環(huán)體這個代碼塊內溺职,因此在循環(huán)外就不能使用了岔擂。另外,for循環(huán)會對該變量做特殊處理浪耘,讓每次循環(huán)使用的都是一個獨立的循環(huán)變量乱灵。
二、變量的提升問題
用var
定義的變量先賦值再聲明是沒有任何問題的七冲,因為里面會有變量提升的情況阔蛉。
而用let
定義的變量不會被提升,這里有個暫時性死區(qū)的概念
暫時性死區(qū)
使用
let
或const
聲明的變量癞埠,在到達聲明處之前都是無法訪問的,會被放置在JS社區(qū)稱為暫時性死區(qū)( temporal dead zone ,TDZ )的區(qū)域內聋呢,試圖訪問會導致一個引用錯誤苗踪。雖然該名稱并未在 ECMAScript 規(guī)范中被明確命名,但經(jīng)常被用于描述
let
或const
聲明的變量為何在聲明處之前無法被訪問削锰。
下面放一個先賦值再聲明會直接報 Cannot access 'a' before initialization 的錯誤的例子
三通铲、全局定義的變量不再作為屬性添加到全局對象中
在全局使用var
定義的變量會被掛載到全局也就是window對象中
而使用let
定義的變量并不會被掛載到全局對象中
四、不可重復定義同名變量
var
在重復定義同名變量的時候并不會報錯器贩,最終打印會是最后一個所賦的值
let
重復定義同名變量會直接報 Identifier 'a' has already been declared 的錯誤
下面來聊聊const
的使用
const
和let
同樣具有塊級作用域颅夺,且聲明不會被提升的特點朋截。- 使用
const
定義變量時,必須初始化
在過去只有var
一個關鍵字吧黄,沒有辦法清晰的表明這個變量是否需要修改部服,而新增了let
和const
關鍵字后,可以使用let
來聲明可以被修改的變量拗慨,使用const
來聲明不會被修改的變量廓八,而使用const
聲明的變量會被認為是常量( constant ),這樣語義上會更加清晰赵抢。
如果我們嘗試修改const
定義的變量剧蹂,會報Assignment to constant variable錯誤。
由于不可以被更改的特性烦却,那么我們用const
定義變量的時候就必須初始化宠叼,不然會報Missing initializer in const declaration的錯誤,而使用var
和let
的話其爵,可以先聲明后面需要的時候再賦值冒冬。