• (1) let和const


    一、let命令

    1. 基本语法

    ES6中新增加了let语法,用来声明变量。它的用法与var类似,但是只有在let命令所在的代码块内部才有效。

    而for循环的计数器,就很适合let命令。

    for (let i = 0; i < 5; i++) {
        console.log(i);
    }

    上面的i只在for循环内部是有效的。不像我么平时定义的var,是在循环的外部,就像这样:

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

    由于我们从前会碰到很多的问题,而在ES6中,我们都可以直接使用let啦!我的建议是在for循环里一律使用let,防止不必要的麻烦和错误。

    2. 不存在变量提升

    let和var的区别在于,let必须要在声明后使用,否则就会报错。

    console.log(foo); // 输出undefined
    console.log(bar); // 报错ReferenceError
    var foo = 2;
    let bar = 2;

    其中输出undefined大家都清楚,是因为在解析的时候存在变量提升,所以运行的时候其实是var foo,在console.log(foo),所以由于未赋值,当然的就产生了undefined;而let不存在变量提升,所以自然地就报错了。

    3. 暂时性死区

    只要块级作用域内存在 let 命令, 它所声明的变量就绑定binding) 这个区域, 不再受外部的影响。

    var tmp = 123;
    if (true) {
       tmp = 'abc';
       let tmp;
    }

    上面代码中, 存在全局变量 tmp , 但是块级作用域内 let 又声明了一个局部变量 tmp , 导致后者绑定这个块级作用域, 所以在 let 声明变量前, 对 tmp 赋值会报错。

    ES6明确规定, 如果区块中存在 let const 命令, 这个区块对这些命令声明的变量, 从一开始就形成了封闭作用域。 凡是在声明之前就使用这些变量, 就会报错。

    这样的设计是为了让大家养成良好的编程习惯, 变量一定要在声明之后使用, 否则就报错。

    ES6规定暂时性死区和不存在变量提升, 主要是为了减少运行时错误, 防止在变量声明前就使用这个变量, 从而导致意料之外的行为。 这样的错误在ES5是很常见的, 现在有了这种规定, 避免此类错误就很容易了。

    4. 不允许重复声明

    let不允许在相同作用域内, 重复声明同一个变量。

    // 报错
    function () {
    let a = 10;
    var a = 1;
    }

    二、块级作用域

    1. 为什么需要块级作用域

    ES5只有全局作用域和函数作用域, 没有块级作用域, 这带来很多不合理的场景。

    (1) 第一种场景, 内层变量可能会覆盖外层变量。

    var tmp = new Date();
    function f() {
        console.log(tmp);
            if (false) {
                var tmp = "hello world";
            }
    } 
    f();
    // undefined

    为什么是undefined呢?其实不难理解,就是f()内部的tmp变量提升到了函数作用域的顶部,所以也就获取不到外部的tmp了。

    (2) 第二种场景, 用来计数的循环变量泄露为全局变量

    这正是我一开始谈到的var不是在for循环内部,而是在它的前面定义的,所以如果for循环是在全局作用域中,我们定义的 i 则会泄露成全局变量。

    2. ES6的块级作用域

    let 实际上为JavaScript新增了块级作用域。

    function f1() {
        let n = 5;
        if (true) {
          let n = 10;
    } 
        console.log(n); // 5
    }

    如果使用var定义呢?那么最后的输出结果将会是10。而使用let自动的将作用域绑定在了自己所在的作用域内部,我们可以看出来,嘿嘿,这东西多么好用了吧?

    可能以后我们都将会抛弃var。

    块级作用域的出现, 实际上使得获得广泛应用的立即执行匿名函数( IIFE) 不再必要了。

    // IIFE写法
      (function () {
        var tmp = ...;
        ...
      }());
    
    // 块级作用域写法
      {
        let tmp = ...;
        ...
      }

    另外, ES6也规定, 函数本身的作用域, 在其所在的块级作用域之内。

     

    三、 const命令

    const 声明一个只读的常量。 一旦声明, 常量的值就不能改变。

    const声明的变量不得改变值, 这意味着, const一旦声明变量, 就必须立即初始化, 不能留到以后赋值。

    const的作用域与let命令相同: 只在声明所在的块级作用域内有效。

    const命令声明的常量也是不提升, 同样存在暂时性死区, 只能在声明的位置后面使用。

    const声明的常量, 也与 let 一样不可重复声明。

    对于复合类型的变量, 变量名不指向数据, 而是指向数据所在的地址。 const命令只是保证变量名指向的地址不变, 并不保证该地址的数据不变, 所以将一个对象声明为常量必须非常小心 。

    ES5只有两种声明变量的方法: var 命令和 function 命令。 ES6除了添加 let const 命令, 后面章节还会提到, 另外两种声明变量的方法: import 命令和 class 命令。 所以, ES6一共有6种声明变量的方法。

    四、 全局对象的属性

    全局对象是最顶层的对象, 在浏览器环境指的是 window 对象, 在Node.js指的是 global 对象。 ES5之中, 全局对象的属性与全局变量是等价的。

    未声明的全局变量, 自动成为全局对象 window 的属性, 这被认为是JavaScript语言最大的设计败笔之一。

    ES6为了改变这一点, 一方面规定, 为了保持兼容性, var 命令和 function 命令声明的全局变量, 依旧是全局对象的属性; 另一方面规定, let 命令、 const 命令、 class 命令声明的全局变量, 不属于全局对象的属性。 也就是说, 从ES6开始, 全局变量将逐步与全局对象的属性脱钩。

     

  • 相关阅读:
    sql2000如何完美压缩.mdf文件
    SQL Server读懂语句运行的统计信息 SET STATISTICS TIME IO PROFILE ON
    Sql Server性能优化辅助指标SET STATISTICS TIME ON和SET STATISTICS IO ON
    理解性能的奥秘——应用程序中慢,SSMS中快(6)——SQL Server如何编译动态SQL
    理解性能的奥秘——应用程序中慢,SSMS中快(5)——案例:如何应对参数嗅探
    理解性能的奥秘——应用程序中慢,SSMS中快(4)——收集解决参数嗅探问题的信息
    理解性能的奥秘——应用程序中慢,SSMS中快(3)——不总是参数嗅探的错
    理解性能的奥秘——应用程序中慢,SSMS中快(2)——SQL Server如何编译存储过程
    巧用Map缓存提升"翻译"速度
    pt-archiver配置自动归档
  • 原文地址:https://www.cnblogs.com/luohaoran/p/6054427.html
Copyright © 2020-2023  润新知