es6 快速入門 系列 —— 變量聲明:let和const

其餘章節請看:javascript

es6 快速入門 系列html

變量聲明:let和const

試圖解決的問題

經典的 var 聲明讓人迷惑java

function demo1(v){
    if(v){
        var color='red'
    }
    console.log(color)
}
demo(1) // red

js引擎會將上面的 demo1 函數修改爲下面的樣子:es6

function demo2(v){
    var color;
    if(v){
        color='red'
    }
    ...
}

解決方法

var 聲明改成 let 聲明函數

function demo3(v){
    if(v){
        let color='red'
    }
    // 變量color在此處不存在
    console.log(color)
}

demo3(1) // 報錯

let聲明的用法與var相同。用 let 代替 var 來聲明變量,就能夠把當前做用域限制在當前代碼塊(指塊級做用域)中。因爲 let 聲明不會被提高,所以開發者一般將 let 聲明語句放在代碼塊頂部,以便整個代碼塊均可以訪問code

最佳實踐

起初,對不少js開發者來講,let與他們實際想要的var同樣,因此直接將var 替換成let。當更多的開發者遷移到es6後,另外一種作法日益普及:默認使用const,只有確實須要改變變量的值才使用let,可能大部分的值在初始化後不會再改變。htm

補充

塊級做用域

之前只有函數做用域,es6新增了塊級做用域(字符{和}之間的區域)blog

// 函數做用域:變量i在函數demo4中有效
function demo4(){
    if(true){
        var i = 1
    }
    console.log(i)
    
}
demo4() // 1
console.log(i) // 報錯(i沒有定義)
// 塊級做用域:變量i只在if中的{和}之間有效
function demo5(){
    if(true){
        let i = 1
    }
    console.log(i)
    
}
demo5() // 報錯(i沒有定義)

禁止重複聲明

假設做用域中存在某變量(i),此時再用 letconst 關鍵字聲明變量(i),就會拋出錯誤ip

var a = 1;
// 重複聲明,拋出語法錯誤
let a = 1;
var a = 1;
if(1){
    // 不會拋出錯誤(沒有重複聲明)
    let a = 1;
}

const聲明

es6提供 const 關鍵字來聲明常量作用域

常量必須一開始就初始化

// 正確
const i = 1
// 報錯(常量未初始化)
const j;

不能夠爲 const 定義的常量再賦值(但容許修改值)

// 報錯
const i = 1;
i = 2;
const obj = {}
// 正確(容許修改值)
obj.i = 1
// 錯誤(不容許修改綁定)
obj = {}

臨時死區

用 let 或 const 聲明的變量,會先存放在臨時死區(TDZ)中,只有執行過變量聲明語句後,變量才從TDZ中移除

if(true){
    // 報錯(訪問臨時死區中的變量,會報錯)
    console.log(typeof i)
    let i = 1
}

循環中的塊做用域綁定

var 聲明讓開發者建立函數很是困難

var funArr = []

for(var i = 0; i < 5; i++){ 
    funArr.push(function(){
        console.log(i)
    })
}

funArr[0]() // 5
funArr[1]() // 5

咱們的預期是輸出0~4,這裏卻所有輸出5

能夠用當即調用函數表達式(IIFE)來達到目的,就像這樣:

var funArr = []

for(var i = 0; i < 5; i++){ 
    funArr.push(function(i){
        return function(){
            console.log(i)
        }
    }(i))
}

funArr[0]() // 0
funArr[1]() // 1

但咱們能夠用更簡單的方式:循環中用 let 聲明

var funArr = []
// 循環中用let聲明:var 改用 let聲明
for(let i = 0; i < 5; i++){
    // let聲明模仿上述例子中 IIFE 所作的一切(每次循環都建立一個新變量i,給新變量i賦值),
    // 如今完全刪除 IIFE 以後仍可獲得預期的結果
    funArr.push(function(){
        console.log(i)
    })
}

funArr[0]() // 0
funArr[1]() // 1

注:let聲明在循環內部的行爲是標準中專門定義的,不必定與 let 的不提高特性相關

全局塊做用域綁定

var 聲明的變量,會覆蓋已存在的全局屬性;let 和 const 聲明的變量不會覆蓋全局屬性

// 覆蓋全局屬性RegExp
var RegExp = 'hello'
console.log(window.RegExp) // hello
let RegExp = 'hello'
console.log(window.RegExp) // RegExp() { [native code] }
console.log(RegExp) // hello

其餘章節請看:

es6 快速入門 系列

相關文章
相關標籤/搜索