es6基礎0x002:var、let、const、塊級做用域、暫存死區

0x001 var

  1. 語法babel

    var varname1 [= value1 [, varname2 [, varname3 ... [, varnameN]]]];
  2. 使用閉包

    var a, b=2 // 聲明多個變量,能夠賦值,也能夠不賦值
    a=1 // 先聲明,再賦值
  3. var變量提高
    使用var聲明的變量將會被提高到函數的頂部app

    console.log(a) // undefined
    var a =2  
    console.log(a) // 2
    console.log(b) //Uncaught ReferenceError: b is not defined...

    以上代碼至關於函數

    var a
    console.log(a) // undefined
    a=2
    console.log(a) // 2
    console.log(b) //Uncaught ReferenceError: b is not defined...

0x002 let

  1. 語法翻譯

    let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]];
  2. 使用code

    let a, b = 2 // 聲明多個變量,賦值不賦值無所謂
    a = 2 // 聲明以後再賦值
  3. 再也不提高事件

    console.log(a) // Uncaught ReferenceError: a is not defined...
    let a=1

    注意:猜想, 使用babel翻譯一下代碼發現,只是let變成了var,因此使用babel轉義以後的代碼依舊會提高作用域

  4. 不能重複聲明get

    let a=1
    let a=2 // Uncaught SyntaxError: Identifier 'a' has already been declared

0x003 const

  1. 語言it

    const name1 = value1 [, name2 = value2 [, ... [, nameN = valueN]]];
  2. 使用

    const a=1, b=2 // 不能省略的值
  3. 不能省略的值

    const c // Uncaught SyntaxError: Missing initializer in const declaration
  4. 不能重複賦值

    const d=4
    d=5 // Uncaught TypeError: Assignment to constant variable.
  5. 能夠修改的引用

    const e=[]
    e[0]=0
    console.log(e) //[0]

0x004 塊級做用域

塊級做用域是隨着letconst而來最有用的特性了,在以前的js中,js的做用域是函數級的,由此帶來的幾個臭名昭著的問題:

  • 意外被修改的值

    function varTest() {
      var x = 1;
      if (true) {
        var x = 2;  // 一樣的變量!
        console.log(x);  // 2
      }
      console.log(x);  // 2
    }

    可使用let避免了

    function letTest() {
      let x = 1;
      if (true) {
        let x = 2;  // 不一樣的變量
        console.log(x);  // 2
      }
      console.log(x);  // 1
    }
  • 萬惡的for循環和點擊事件

    var list = document.getElementById("list");
    
    for (var i = 0; i < 5; i++) {
      var item = document.createElement("LI");
      item.appendChild(document.createTextNode("Item " + i));
    
      item.onclick = function (ev) {
        console.log("Item " +i + " is clicked.");
      };
      list.appendChild(item);
    }
    console.log(i) // 5

    若是點擊上面,無論點擊哪一個,顯示出來的都是Item 5 is clicked.,雖然可使用閉包解決,可是如今有了更好的方案

    let list = document.getElementById("list");
    
    for (let i = 0; i < 5; i++) {
      let item = document.createElement("LI");
      item.appendChild(document.createTextNode("Item " + i));
    
      item.onclick = function (ev) {
        console.log("Item " +i + " is clicked.");
      };
      list.appendChild(item);
    }

0x005 做用域規則很簡單

  1. {}塊內造成一個做用域,包括ifelsewhileclassdo...while{}function

    {
        const f=6
    }
    console.log(f) // Uncaught ReferenceError: f is not defined
  2. for循環中用let聲明一個初始因子,該因子在每一個循環內都是一個新的做用域

    for (let i = 0; i < 10; i++) {
      console.log(i);
    }
    console.log(i) // Uncaught ReferenceError: i is not defined
  3. switch只有一個做用域

    switch (x) {
      case 0:
        let foo;
        break;
        
      case 1:
        let foo; 
        break;
    }
    // Uncaught SyntaxError: Identifier 'foo' has already been declared

0x006 暫存死區-Temporal Dead Zone-TDZ

隨着letconst的引入,也引入了暫存死區的概念。使用var的時候,做用域內(函數做用域),在還沒使用var聲明一個變量的時候,訪問該變量,將會得到undefined。可是若是使用let,做用域(塊級做用域)內,在還沒使用let聲明一個變量的時候,訪問該變量,將會得到ReferenceError,從做用域開始到let語句之間,就是暫存死區。

{
 console.log(a) // Uncaught ReferenceError: a is not defined
 console.log(b) // Uncaught ReferenceError: b is not defined
 console.log(c) // undefined
 // 暫存死區
 let a =1
 const b=2
 var c=3
}

注意:猜想, 使用babel翻譯一下代碼發現,只是let變成了var,因此使用babel轉義以後可能不存在暫存死區

0x007 總結

儘可能使用letconst,若是但願改變該變量的值,則使用let,若是但願再也不改變該變量的值或者引用,則使用const,讓var成爲歷史。

相關文章
相關標籤/搜索