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