• let 、 const 、 块级作用域


    写在前面

    ES6 声明变量的 6 种方法

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

    块级作用域

    为什么需要块级作用域

    ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。比如内层变量可能会覆盖外层变量;用来计数的循环变量泄露为全局变量

    • let 实际上为 JavaScript 新增了块级作用域。
      块级作用域的出现,实际上使得获得广泛应用的立即执行函数表达式(IIFE)不再必要了。

    块级作用域与函数声明

    • 在浏览器的 ES6 环境中,块级作用域内声明的函数,行为类似于 var 声明的变量;
    • 另外,还有一个需要注意的地方。ES6 的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。

    let

    不存在变量提升

    • let 所声明的变量只在其所在的代码块内有效
    • let 不存在变量提
      var 所声明的变量在脚本运行前就将变量都定义了,在脚本中的赋值语句中再对其进行赋值操作,所以变量可以在声明之前使用,值为undefined
      let 纠正了这种语法行为,它所声明的变量一定要在变量声明后使用,否则报错

    暂时性死区(temporal dead zone,简称 TDZ)

    • ES6 中如果在区块中存在 letconst ,则区块对这些命令声明的变量从一开始就形成了封闭作用域,凡是在声明之前使用这些变量都会报错
    • ES6 规定暂时性死区和 letconst 语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。这样的错误在 ES5 是很常见的,现在有了这种规定,避免此类错误就很容易了。
    • 在没有let之前,typeof 运算符是百分之百安全的,永远不会报错。现在这一点不成立了。这样的设计是为了让大家养成良好的编程习惯,变量一定要在声明之后使用,否则就报错。

    ES6 规定暂时性死区和let、const语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。这样的错误在 ES5 是很常见的,现在有了这种规定,避免此类错误就很容易了。
    总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

    不允许重复声明

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

    const

    • const 声明一个只读的常量。一旦声明,常量的值就不能改变;(这意味着,const 一旦声明变量,就必须立即初始化,不能留到以后赋值)
    • const 的作用域与let命令相同:只在声明所在的块级作用域内有效。
    • const 命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。

    const 的本质

    const 实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const 只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。

    • 如果真的想将对象冻结,应该使用Object.freeze方法。

      const foo = Object.freeze({});
      // 常规模式时,下面一行不起作用;
      // 严格模式时,该行会报错
      foo.prop = 123;</pre>
      

      上面代码中,常量foo指向一个冻结的对象,所以添加新属性不起作用,严格模式时还会报错。
      除了将对象本身冻结,对象的属性也应该冻结。下面是一个将对象彻底冻结的函数。

      var constantize = (obj) => {
          Object.freeze(obj);
          Object.keys(obj).forEach( (key, i) => {
              if ( typeof obj[key] === 'object' ) {
                  constantize( obj[key] );
              }
          });
      };
      
    HAVE A NICE DAY!
  • 相关阅读:
    读写ini文件
    优化SQL Server的内存占用之执行缓存
    跨应用程序进行 Forms 身份验证
    MSDN Visual系列:在MOSS中创建一个BDC实体
    Sql Server中利用自定义函数完成单据流水号的设计
    关于string是值类型还是引用类型
    经典算法C#四种排序算法
    用C#实现HTTP协议下的多线程文件传输
    Windows Phone关于 Llistpicker用法
    Hubtile的应用
  • 原文地址:https://www.cnblogs.com/apimhnkj/p/10123435.html
Copyright © 2020-2023  润新知