前言
ES6 新增了 let
命令,用来申明变量。它的用法相似于 var
。const
申明一个只读的常量。一旦申明,常量的值就不能扭转。
let:申明的是变量
一、不存在变量晋升
var
命令会产生“变量晋升”景象,即变量能够在申明之前应用,值为undefined
。这里就不具体说这个货色,有须要的能够看我 详解 javascript 变量晋升 这个文章。
为了纠正这种景象,let
命令扭转了语法行为,它所申明的变量肯定要在申明后应用,否则报错。
// var 的状况
alert(foo); // 输入 undefined
var foo = 2;
// let 的状况
alert(bar); // 报错 ReferenceError
let bar = 2;
下面代码中,变量 foo
用var
命令申明,会产生变量晋升,即脚本开始运行时,变量 foo
曾经存在了,然而没有值,所以会输入 undefined
。变量bar
用let
命令申明,不会产生变量晋升。这示意在申明它之前,变量 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.1415
PI = 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 只保障变量名指向的地址不变,并不保障该地址的数据不变,所以将一个复合类型的变量申明为常量必须十分小心。