變數與塊級作用域
ECMAScript 6.0(以下簡稱 ES6)是 JavaScript 語言的下一代標準,已經在 2015 年 6 月正式發布了。它的目標,是使得 JavaScript 語言可以用來編寫複雜的大型應用程序,成為企業級開發語言。
ES6的出現已經很久了,由於之前的項目只是基於ES5以及之前的版本內容進行開發的,所以沒有系統性的梳理學習ES6的相關知識。感覺自己已經被發展的車輪落下了好遠好遠(@﹏@)~,所以在接下來這段時間針對性的進行學習整理,希望能夠讓自己有所提高,也希望能幫助和我一樣的人……
變數
常量 const命令
常量的定義
在之前的版本ES5甚至更早的版本(後面統稱ES5)中,很少能夠聽到常量的概念,我們也知道,JS不同於其他的語言,如Java、C++等,有常量的概念。雖然通過其他的方法能夠達到實現常量的方法,但是並不直接、方便。
如可通過下述方式進行常量的實現:
在ES6中,定義一個常量則非常簡單,通過const進行聲明即可。
const聲明一個只讀的常量。一旦聲明,常量的值就不能改變。
const聲明的變數不得改變值,這意味著,const一旦聲明變數,就必須立即初始化,不能留到以後賦值。
const定義常量的本質
const實際上保證的,並不是變數的值不得改動,而是變數指向的那個內存地址不得改動。對於簡單類型的數據(數值、字元串、布爾值),值就保存在變數指向的那個內存地址,因此等同於常量。但對於複合類型的數據(主要是對象和數組),變數指向的內存地址,保存的只是一個指針,const只能保證這個指針是固定的,至於它指向的數據結構是不是可變的,就完全不能控制了。
如:
let命令
在ES6中新增了let命令,可以用來聲明一個變數,作用類似於之前常用的var,但是和var聲明的變數其有效的作用域不同,let聲明的變數只在let命令所在的代碼塊內有效。
如:
通過上面代碼的執行結果來看能夠看出,let聲明的變數只在它所在的代碼塊中有效,即{}所在的代碼塊內。
那麼let聲明的變數在什麼情況下會比較有用呢?先讓我們來看下下面一段代碼:
可能我們預期的結果是顯示0,2,4,但是從執行代碼的結果中能夠看出,得到的卻是6,6,6,這是為什麼呢?首先我們上面是使用的var聲明的一個i變數,此處會有一個變數提升,相當於在for循環外面聲明了var i = 0變數。當在for循環中時,arrays[i]中的i即為每次循環的i的值(0,1,2),但是在函數體中並沒有將i變數取值為每次循環的值,它只是對變數的一個引用,並不是值的引用。當在執行循環中的函數體時,i變數已經變成了3,所以每次的結構輸出都是6。這個時候,ES6中的let命令就能夠滿足我們的要求了。
上面代碼中變數i只在for循環體內有效,只在其所在的塊作用域內有效,每次for循環時會將i變數的值保存在其對應的塊作用域中(for循環的{}),每一輪循環都是重新生成一個新的作用域,在執行for循環中聲明的函數時,都會獲取其對應作用域內的i的值。這部分涉及到的作用域相關的概念,我們後面會說到。
1、在前面提到過,var命令聲明的變數會發生變數提升的現象,即變數可以在聲明之前使用,值為undefined。按照一般的邏輯來說,變數應該在聲明語句之後才可以使用。所以在ES6中為了糾正這個現象,let命令改變了語法行為,它所聲明的變數一定要在聲明後使用,否則報錯。
2、只要在塊級作用域中存在let命令,它所聲明的變數就「綁定」(binding)這個區域,不再受外部的影響。
ES6 明確規定,如果區塊中存在let和const命令,這個區塊對這些命令聲明的變數,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變數,就會報錯。
總之,在代碼塊內,使用let命令聲明變數之前,該變數都是不可用的。這在語法上,稱為「暫時性死區」(temporal dead zone,簡稱 TDZ)。
3、typeof不再是一個完全安全的操作。之前我們知道,針對一個沒有生命的變數調用typeof方法時會返回undefined,但是在上面出現的「暫時性死區」中,typeof將會被報錯。
使用let聲明變數時,只要變數在還沒有聲明完成前使用,就會報錯。
4、let不允許在相同作用域內,重複聲明同一個變數。
塊級作用域
為什麼需要塊級作用域
1、內層變數可能會覆蓋外層變數
內層的tmp變數由於變數提升覆蓋了外層的tmp變數,導致輸出不符合預期
2、計數的循環變數泄露為全局變數
我們上面用到的for循環的例子就是這個現象的證明,var聲明的變數i在循環結束後泄露成了全局變數。
ES6的塊級作用域
在ES6中{}包裹的塊即為一個塊級作用域,並且塊級作用域支持嵌套,如
並且外層作用域不能讀取內層作用域的變數;內層作用域可以定義外層作用域的同名變數。
在之前的版本中,當我們想要實現一個變數只在一個代碼塊中運行,我們往往需要通過使用立即執行函數來實現。如
但是在ES6中則不再必要了,我們可以通過塊級作用域就能夠實現
本次主要針對ES6中的變數和塊級作用域進行了梳理學習,並且通過與ES5的實現方式進行了對比,從而看出其變化以及快捷與便利。希望能夠對您有所幫助,如有寫的不對的地方望請指正,從而共同進步。
TAG:冷星學前端 |