使用var關鍵字聲明的變量,不管其實際聲明位置在何處,都會被視爲聲明於所在函數的頂部(若是聲明不在任意函數內,則被視爲在全局做用域的頂部)。這就是所謂的變量提高(hoisting)es6
後臺實際上會轉化成這樣瀏覽器
value變量的聲明被提高到了頂部,而初始化工做則保留在原處。這覺得着在else分支value的變量也是可訪問的,此處它的值會是undefined,由於它並無被初始化。安全
塊級聲明也就是讓所聲明的變量在指定快的做用域外沒法被訪問。塊級做用域在以下狀況被建立;
1 在一個函數內部
2 在一個代碼塊(由一對花括號包裹)內部函數
let聲明語法域var語法一致spa
let聲明沒有被提高到函數定義的頂部,這樣使用會報3d
上面就是塊級做用域的基本使用。下面會帶來一點let和var特別的地方對象
若是一個標識符已經在代碼塊內部被定義,那麼在此代碼塊內使用同一個標識符進行let聲明就會致使拋出錯誤blog
上面會報錯,可是var聲明是不會的ip
不在同一級別聲明變量,不會報錯,這個新變量會屏蔽全局的
count變量,從而在局部阻止對於後者的訪問。作用域
const常量,它們的值在被設置完成後就不能再被改變,全部的const變量都須要在聲明試進行初始化。
對比常量聲明與let聲明
1 常量聲明與let聲明,都是塊級聲明。這意味着常量在聲明它們的語句塊外部是沒法訪問的,而且聲明也不會被提高
2 const變量和let另外一個類似的地方,也是禁止重複聲明
使用const聲明對象
const聲明會阻止對於變量綁定與變量自己自身值的修改,這意味着const聲明並不會阻止對變量成員的修改
記住:const阻止的是變量綁定的修改,而不是阻止對成員值的修改。
使用let或const聲明的變量,在達到聲明處以前都是沒法訪問的,試圖訪問會致使一個引用錯誤,即便在一般是安全的操做時(例如使用typeof運算符),也是如此
對比var let明顯使用let符合咱們的使用指望。
上述緣由由於變量i在循環的每次迭代被共享了(沒有塊級做用域)
爲了修正這個問題,開發者在循環內使用當即調用函數表達式,以便在每次迭代中強制建立變量的一個新副本
幸運的是使用let完美解決這個問題
let每次使用完,就銷燬從新建立。
在常規的for循環中,你能夠初始化時使用const。但循環會在試圖改變該變量的值時拋出錯誤。
BUT!!!!!!!!!!!!!
const變量在for-in或for-of循環中使用時,與let變量效果相同。
let與const不一樣於var的另外一個方面是在全局做用域上的表現。當在全局做用域上使用var時,它會建立一個新的全局變量,併成爲全局對象(在瀏覽器中是window)的一個屬性,這意味着使用var可能會無心覆蓋一個已有的全局屬性
然而若你在全局做用域上使用let或者const。雖然在全局做用域上會建立新的綁定,但不會有任何屬性被添加到全局對象上。這也就意味着你不能使用let或const來覆蓋一個全局變量,你只能將其屏蔽。
在es6的發展階段,被普遍承認的變量聲明方式是:默認狀況下應當使用let而不是var。對於多數js開發者來講,let的行爲方式正式var本應有的方式,所以直接用let代替var更符合邏輯。
然而隨着更多的開發者遷移到es6上,一種代替方案變得更爲流行。那就是默認狀況下使用const,而且只在知道變量值須要被更改的狀況下才使用let。其理論依據是大部分變量在初始化以後都不該當被修改,覺得預期外的改動是bug的源頭之一。
let 與 const 塊級綁定將詞法做用域引入js。這兩種聲明方式都不會進行提高。而且只會在聲明它們的代碼塊內部存在。因爲變量可以再必要位置被準確聲明,其表現更加接近其餘語言,而且能減小無意錯誤的產生,做爲一個反作用,你不能在變量聲明位置以前訪問它們,即使使用的是typeof 這樣的安全運算符,因爲塊級綁定存在暫時性死區,試圖在聲明位置以前訪問它就會致使錯誤。
let與const的表如今不少狀況下都類似與var ,而後在循環中就不是這樣,在for-in與for-of循環中。let與const都能每一次迭代時建立一個新的綁定,這意味着在循環體內建立的函數可使用當前迭代所綁定的循環變量值(而不是像使用var那樣,統一使用循環結束時的變量值)。這一點在for循環中使用let聲明時也成立,不過在for循環中使用const聲明則會致使錯誤。
塊級綁定當前的最佳實踐就是:在默認狀況下使用const.而只在你知道變量值須要被更改的狀況下才使用let。這在代碼中可以確保基本層次的不可變性,有助於防止某些類型的錯誤。