ES6 塊級做用域

這是我參與8月更文挑戰的第5天,活動詳情查看:8月更文挑戰javascript

let 與 const

ES5 中聲明變量命令只有兩種 var 和 functionjava

ES6 中除了 var、function,新增了 let、const、class、import,一共六種chrome

  1. let 是 ES6 新增的聲明命令,功能相似於 ES5 中的 var 關鍵字瀏覽器

  2. let 聲明的變量盡在所在代碼塊內有效markdown

    {
        let a = 0
        var b = 1
    }
    console.log(b) // 1
    console.log(a) // ReferenceError
    // 這代表 let 聲明的變量只在它所在的代碼塊有效
    複製代碼

    let 命令很適合在 for 循環中使用ide

    var a = [];
    for (var i = 0; i < 10; i++) {
      a[i] = function () {
        console.log(i);
      };
    }
    a[6](); // 10
    // var 聲明的 i,全局有效,每一次循環,新的 i 值都會覆蓋舊值,致使最後輸出的是最後一輪的 i 的值
    
    var b = [];
    for (let j = 0; j < 10; j++) {
      b[j] = function () {
        console.log(j);
      };
    }
    b[6](); // 6
    // 變量 j 使用 let 聲明,當前的 j 只在本輪循環有效,每一次循環的 j 其實都是一個新的變量,因此最後輸出的是 6
    複製代碼
  3. let 命令不容許重複聲明函數

    // SyntaxError
    function test1() {
      let a = 10
      var a = 1
    }
    // SyntaxErrot
    function test2() {
      let a = 10
      let a = 1
    }
    // SyntaxError
    function test3(a) {
        let a = 1
    }
    複製代碼
  4. 暫行性死區post

    // ReferenceError
    console.log(a)
    let a = 0
    複製代碼

    同一代碼塊中,使用 let 命令聲明的變量,不能在聲明以前使用,會報引用錯誤ui

    代碼塊中,變量聲明前,該變量不可用,語法上稱之爲暫行性死區(temporal dead zone,簡稱 TDZ)spa

  5. const 和 let 做用和特性相似,只在當前代碼塊有效,不能重複聲明

    const 聲明時必須賦初值,且不可改變其值

    const a = 1
    a = 2 // TypeError
    const b // SyntaxError
    複製代碼
  6. let、const 變量提高

    下面代碼 let 重複聲明會報語法錯誤,但在報錯以前 console.log 不能正常輸出

    說明存在變量提高

    let a = 1
    console.log(a)
    let a = 2 // SyntaxError
    複製代碼

    可是因爲暫行性死區的存在,咱們沒法在聲明以前使用變量

    console.log(a) // undefined
    console.log(b) // ReferenceError
    
    var a = 2
    let b = 2
    複製代碼

    注:變量的定義分爲建立 -> 初始化爲 undefined -> 賦值三個階段

    let 的建立過程被提高,可是初始化沒有提高

    var 的建立和初始化被提高

    function 的建立、初始化和賦值都被提高

塊級做用域

  1. ES5 中只有全局做用域和函數做用域

    // 全局做用域
    var a = 0
    
    function test() {
        // 函數做用域
        var a = 1
    }
    複製代碼

    存在的問題

    var a = 0
    function test() {
        console.log(a)
        if(false) {
            var a = 1
        }
    }
    test() // undefined
    
    複製代碼

    函數做用域下中 if 中 var a 命令變量提高,致使 a 爲 undefined

  2. ES6 中規定 {} 內部爲一個獨立的塊級做用域

    外層代碼塊不受內層代碼塊的影響

    外層做用域沒法讀取內層做用域的變量

    內層做用域能夠定義外層做用域的同名變量

    {{
      let a = 0
      {
          let a = 1
          {
              console.log(a) // 報錯
          }
      }
    }}
    複製代碼
  3. 塊級做用域的出現讓普遍運用的的當即執行函數再也不必要

    // IIFE 寫法
    (function () {
      var tmp = ...;
      ...
    }());
    
    // 塊級做用域寫法
    {
      let tmp = ...;
      ...
    }
    複製代碼

函數聲明

  1. ES5 規定函數只能在全局做用域和函數做用域中聲明

    // 狀況一
    if (true) {
      function fn() {}
    }
    
    // 狀況二
    try {
      function fn() {}
    } catch(e) {
    }
    複製代碼

    以上爲非法的聲明,可是爲了兼容舊代碼,瀏覽器沒有遵照此規定,能夠運行,不會報錯,可是嚴格模式下會報錯

    // ES5 嚴格模式
    'use strict';
    if (true) {
      function fn() {}
    }
    // 報錯
    複製代碼
  2. ES6 引入塊級做用域,明確容許能夠在塊級做用域聲明函數

    // ES6 嚴格模式
    'use strict';
    if (true) {
      function fn() {}
    }
    // 不報錯
    複製代碼
  3. ES6 規定塊級做用域中的函數聲明,沒法在做用域外引用

    function fn() { 
        console.log('outside') 
    }
    (function () {
      if (false) {
        // 重複聲明一次函數
        function fn() { 
            console.log('inside')
        }
      }
      fn()
    }())
    複製代碼

    在 ES5 中會打印出 inside,由於 if 塊裏面的 fn 被提高到自執行函數頭部

    在 ES6 中則打印出 outside,由於在 if 塊內聲明的 fn,做用域外沒法訪問,只能執行外部聲明的 fn

    因爲行爲差別較大,ES6 規定瀏覽器能夠不遵照該項,有本身的行爲方式

    1. 容許在塊級做用域內聲明函數
    2. 函數聲明相似於 var,即提高到全局做用域或函數做用域的頭部
    3. 同時,函數聲明會提高到所在的塊級做用域的頭部

    上面示例代碼在 chrome 環境中可能會報錯,由於實際運行的代碼以下

    function fn() { 
        console.log('outside') 
    }
    (function () {
      var fn = undefined
      if (false) {
        function fn() { 
            console.log('inside')
        }
      }
      fn()
    }())
    // Uncaught TypeError: fn is not a function
    複製代碼
相關文章
相關標籤/搜索