let & const —— ES6基礎總結(二)

老萌學前端發表於2019-05-03

前言

在JS中,var早已深入人心,因此本文將不再贅述,僅在必要時拉出來溜溜。

宣告方式 變數提升 暫時性死區 重複宣告 可修改值 塊級作用域 全域性變數屬於頂層物件
var
let
const 否(引用型別僅保證地址不被修改)

變數提升

    a   // a is not defined
    let a = 'a'
    
    b  // b is not defined
    const b = 'b'
    
    c   // undefined
    var c = 'c'
複製程式碼

暫時性死區

在程式碼塊內,使用letconst命令宣告變數之前,該變數都是不可用的。

其本質是,只要一進入當前作用域,所要使用的變數就已經存在了,但是不可獲取,只有等到宣告變數的那一行程式碼出現,才可以獲取和使用該變數。

    typeof a    // a is not defined
    let a = 'a'
    
    typeof b    // b is not defined
    const b = 'b'
    
    typeof c    // "undefined"
    var c = 'c'
複製程式碼

以下為幾個比較隱蔽的死區:

  1. 賦值

    var a = a
    let b = b   // b is not defined
    複製程式碼
  2. 函式引數

    function foo(a = b, b = 2) {
      console.log([a, b])
    }
    foo()
    複製程式碼

重複宣告

    let a = 'a1'
    let a = 'a2'    // Identifier 'a' has already been declared
    a   // a1
    
    const b = 'b1'
    const b = 'b2'  // Identifier 'b' has already been declared
    b   // b2
    
    var c = 'c1'
    var c = 'c2'
    c   // c2
複製程式碼

修改值

    let a = 'a1'
    a = 'a2'    
    a   // a2
    
    const b = 'b1'
    b = 'b2'  // Assignment to constant variable
    b   // b1
    
    var c = 'c1'
    c = 'c2'
    c   // c2
複製程式碼

const 引用型別僅保證引用地址不可修改

    const a = {
       a1: 1,
       a2: 2
    }
    a.a3 = 3
    a   // {a1: 1, a2: 2, a3: 3}
複製程式碼

塊級作用域

    {
        let a = 'a'     
        const b = 'b'   
        var c = 'c'
    }
    a   // a is not defined
    b   // b is not defined
    c   // c
複製程式碼

全域性變數不再屬於頂層物件

頂層物件:瀏覽器中指window,Node中指global

    let a = 'a'
    window.a    // undefined 
    
    const b = 'b'
    window.b    // undefined 
    
    var c = 'c'
    window.c    // "c"
複製程式碼

再也不用擔心手抖修改了頂層物件~

解決的問題

  1. 內層變數覆蓋外層變數;

    let & const —— ES6基礎總結(二)

  2. 用來計數的迴圈變數變為全域性變數;

    let & const —— ES6基礎總結(二)

    1. 上面程式碼中,變數j是let宣告的,當前的j只在本輪迴圈有效,所以每一次迴圈的j其實都是一個新的變數,那麼如果每一輪迴圈的變數j都是重新宣告的,那它怎麼知道上一輪迴圈的值,從而計算出本輪迴圈的值?這是因為 JavaScript 引擎內部會記住上一輪迴圈的值,初始化本輪的變數j時,就在上一輪迴圈的基礎上進行計算。
    1. for迴圈還有一個特別之處,就是設定迴圈變數的那部分是一個父作用域,而迴圈體內部是一個單獨的子作用域。

    let & const —— ES6基礎總結(二)

  3. 閉包與垃圾回收;

    有塊級作用域

    有塊級作用域

    無塊級作用域

    無塊級作用域

  4. 不再需要使用立即執行函式,減少程式碼冗餘提升可讀性;

  5. 允許在塊級作用域中宣告函式,函式宣告語句的行為類似於let;

    原來,如果改變了塊級作用域內宣告的函式的處理規則,顯然會對老程式碼產生很大影響。為了減輕因此產生的不相容問題,ES6 在附錄 B裡面規定,瀏覽器的實現可以不遵守上面的規定,有自己的行為方式

    1.允許在塊級作用域內宣告函式。

    2.函式宣告類似於var,即會提升到全域性作用域或函式作用域的頭部。

    3.同時,函式宣告還會提升到所在的塊級作用域的頭部。

    注意,上面三條規則只對 ES6 的瀏覽器實現有效,其他環境的實現不用遵守,還是將塊級作用域的函式宣告當作let處理。

參考

  1. ECMAScript 6 入門

  2. 你不知道的JavaScript(上)

小結

本文主要介紹了letconstvar定義變數的區別以及優點。推薦我用了兩個月的時間才理解 let這篇文章,供大家思考。

之前宣告變數只能使用varfunction,現在ES6新增了letconstimportclass4種方式(importclass 後續也會一一總結),所以現在總共有6種宣告變數的方式。SO宣告變數,請合理選擇。

感謝閱讀,如有問題,歡迎指正。

最最最最最後,在這四天的五一小長假裡,為大家獻上美景 —— 摩洛哥藍色小鎮??祝大家五一愉快呦~

摩洛哥藍色小鎮

相關文章