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
    复制代码
相关文章
相关标签/搜索