• 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,这就导致了报错。

  • 相关阅读:
    微信开发SDK使用教程--手机微信群聊新增通知服务端
    微信开发SDK使用教程--手机微信联系人信息上传服务端
    微信开发SDK使用教程--手机端接收发送朋友圈任务指令后数据回传服务端
    微信二次开发SDK使用教程--手机端向服务端发送回复朋友圈评论任务反馈服务端
    js 自执行匿名函数(转载)
    js继承中,原型属性的继承探究
    搭建邮件服务器和使用压测工具的总结
    window.onload和window.document.readystate的探究
    读艾伦的jQuery的无new构建,疑惑分析——jquery源码学习一
    WPF页面 全球化和本地化
  • 原文地址:https://www.cnblogs.com/cc-freiheit/p/9138663.html
Copyright © 2020-2023  润新知