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!
原文地址:https://www.cnblogs.com/apimhnkj/p/10123435.html