前言

ES6 新增了let命令,用来申明变量。它的用法相似于var。 const申明一个只读的常量。一旦申明,常量的值就不能扭转。

let:申明的是变量

一、不存在变量晋升

var命令会产生“变量晋升”景象,即变量能够在申明之前应用,值为undefined。这里就不具体说这个货色,有须要的能够看我 详解 javascript 变量晋升 这个文章。

为了纠正这种景象,let命令扭转了语法行为,它所申明的变量肯定要在申明后应用,否则报错。

// var 的状况alert(foo); // 输入undefinedvar foo = 2;// let 的状况alert(bar); // 报错ReferenceErrorlet bar = 2;

下面代码中,变量foovar命令申明,会产生变量晋升,即脚本开始运行时,变量foo曾经存在了,然而没有值,所以会输入undefined。变量barlet命令申明,不会产生变量晋升。这示意在申明它之前,变量bar是不存在的,这时如果用到它,就会抛出一个谬误

二、暂时性死区,先申明在应用

应用let命令申明变量之前,该变量都是不可用的。

var num = 123;if (true) {  num = 'abc'; // ReferenceError  let num;}

三、不容许反复申明

let不容许在雷同作用域内,反复申明同一个变量。

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

四、块级作用域

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

第一种场景,内层变量可能会笼罩外层变量。

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

下面代码的原意是,if代码块的内部应用外层的tmp变量,外部应用内层的tmp变量。然而,函数f执行后,输入后果为undefined,起因在于变量晋升,导致内层的tmp变量笼罩了外层的tmp变量。

ES6的块级作用域,let实际上为javascript新增的块级作用域。

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

下面的函数有两个代码块,都申明了变量n,运行后输入 20。这示意外层代码块不受内层代码块的影响。如果两次都应用var定义变量n,最初输入的值才是 10。

const:常量

const申明一个只读的常量。一旦申明,常量的值就不能扭转。
const PI = 3.1415;PI // 3.1415PI = 3;// TypeError: Assignment to constant variable.

下面代码表明扭转常量的值会报错。

const的作用域与let命令雷同:只在申明所在的块级作用域内无效
const命令申明的常量也是不晋升,同样存在暂时性死区,只能在申明的地位前面应用。
const申明的常量,也与let一样不可反复申明。
const foo = {};// 为 foo 增加一个属性,能够胜利foo.prop = 123;foo.prop // 123// 将 foo 指向另一个对象,就会报错foo = {}; // TypeError: "foo" is read-only

下面代码中,常量foo贮存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把foo指向另一个地址,但对象自身是可变的,所以仍然能够为其增加新属性。

let和const的相同点:

只在申明所在的块级作用域内无效。
不会产生晋升,同时存在暂时性死区,只能在申明的地位前面应用。
不可反复申明。

let和const的不同点:

let申明的变量能够扭转,值和类型都能够扭转;const申明的常量不能够扭转,这意味着,const一旦申明,就必须立刻初始化,不能当前再赋值
数组和对象等复合类型的变量,变量名不指向数据,而是指向数据所在的地址。const只保障变量名指向的地址不变,并不保障该地址的数据不变,所以将一个复合类型的变量申明为常量必须十分小心。