zoukankan      html  css  js  c++  java
  • ES 6 系列

    let 和 const

    let 声明

      (一)基本用法

        let 声明的变量只在块级作用域内有效,出了该块则报错,最常见且适合的地方在 for 循环中:

    var a = [];
    for (var i = 0; i < 10; i++) {
      a[i] = function () {
        console.log(i);
      };
    }
    a[6]();   // 10
    

      上面的 i 通过 var 方式声明,(循环次数内)全局有效且只有一个,故每次循环结束后, i 的值会被更新,从而导致在完成所有循环后, a 数组中所有的成员中的 i 均指向最后一次更新的值, 即 10,而使用 let 声明:

    var a = [];
    for (let i = 0; i < 10; i++) {
      a[i] = function () {
        console.log(i);
      };
    }
    a[6](); // 6
    

     在每次循环时,该次循环体(代码块)中的 i 只对当前代码块有效,简单而言即:每次循环的 i 相当于一个新的变量,故最终结果是 6 。

      (二)var 的变量提升

        先看一个例子:

    console.log(foo); // 输出undefined
    var foo = 2;
    

        按照正常的逻辑,执行 console 时,变量 foo 在内存中并不存在,但是此时会输出 undefined(未赋值) 错误,这就是 var 声明的变量提升:脚本运行时,变量已经存在,但是没有值,最终输出 undefined。使用 let 声明可以避免变量提升。

       (三)暂时性死区

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

    if (true) {
      // TDZ开始
      tmp = 'abc'; // ReferenceError
      console.log(tmp); // ReferenceError
    
      let tmp; // TDZ结束
      console.log(tmp); // undefined
    
      tmp = 123;
      console.log(tmp); // 123
    }
    

        如上例所示,在 let 命令之前, tmp 变量都不可用, 这块区域都属于 tmp 的 “死区”,语法上称这种现象为 “暂时性死区”。

      注意:1.使用 let 命令时,typeof 不在是一个百分百安全操作;

         2.一个比较隐蔽的死区:

    function bar(x = y, y = 2) {
      return [x, y];
    }
    
    bar(); // 报错
    

      调用 bar() 报错的原因在于 x = y 时,y 并没有声明,属于 “死区”,故报错。解决办法是将函数中参数位置对调即可。

      同理:

    // 不报错
    var x = x;
    
    // 报错
    let x = x;
    // ReferenceError: x is not defined
    

      总之:暂时性锁区的本质是,只要一进入当前作用域,所要使用的变量就已经存在,但是处于不可获取的状态,只有等到声明语句出现,才可以获取和使用。

      (四)块级作用域

      es 5 只有全局和函数作用域两种,接下来看两个 es5 的例子:

      1.内层变量覆盖外层变量

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

      在 fun f() 中,因为存在 var 指令,故可以说在 f() 中就会存在变量提升的现象(而且优先级貌似蛮高的), 所以这就会导致 console undefined 错误,而不是 console 时间;

      2.用来计数的循环变量泄露成全局变量:

    var s = 'hello';
    
    for (var i = 0; i < s.length; i++) {
      console.log(s[i]);
    }
    
    console.log(i); // 5
    

      上例可以看出,在循环结束后,作为控制循环的 i 变量并没有消失,这样就很容易泄露,可能会被恶意利用。

      而 let 的使用为 es 6 新増了块级作用域。

     

    const 声明

      效果跟 java 中的 static final 差不多;

      需要注意:   

        1.const 的变量声明时必须赋值,否则报错;

        2.const 的变量一旦声明,其值只读,不可改变;

        3.const 的作用域与 let 相同: 只在声明所在的块级作用域内有效;

        4.const 的变量不存在变量提升现象,同样存在暂时性死区

        5.const 的变量,不可重复声明;

        6.关于引用类型的对象,一个例子:

    const a = [];
    a.push('Hello'); // 可执行
    a.length = 0;    // 可执行
    a = ['Dave'];    // 报错
    

           常量 a 中存储了一个数组对象的地址,然后这个数组对象中的内容是可变的,但是,最后一行很明显是把一个新的数组对象的地址赋值给 a,这就导致了报错。

  • 相关阅读:
    这些 Drawable 的小技巧,你都了解吗?
    Android 软键盘的显示和隐藏,这样操作就对了
    在 ReactNative 的 App 中,集成 Bugly 你会遇到的一些坑
    聊聊 Material Design 里,阴影的那些事儿!
    PAT 1069 1070 1071 1072
    PAT1021 Deepest Root
    关于素数:求不超过n的素数,素数的判定(Miller Rabin 测试)
    PAT《数据结构学习与实验指导》实验项目集 2-05 2-06 2-07 2-08
    LeetCode:Gas Station
    LeetCode:Candy
  • 原文地址:https://www.cnblogs.com/cc-freiheit/p/9138663.html
Copyright © 2011-2022 走看看