一、let命令
1、基本用法
ES6新增了let命令,用于声明变量。其用法类似于var,但是所声明的变量只在let命令所在的代码块内有效
{
let a = 10;
var b = 1;
}
a//ReferenceError:a is not defined.表明let声明的变量只在其所在代码块内有效
b//1
for循环的计数器很适合适用let命令:
//以下代码中的计数器i只在for循环体内有效,在循环体外就会报错.
for(let i = 0;i < 10;i++){
//...
}
console.log(i);
//ReferenceError:i is not defined
//以下代码中let声明的变量是有效的
var a = [];
for(elt i =0;i < 10;i++){
a[i] = function(){
console.log(i);
};
}
a[6]();//6
2、let声明变量不存在变量提升
var 命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。这种现象多少是有些奇怪的,按照一般的逻辑,变量应该在声明之后才可以使用。
为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明之后使用,否则便会报错。
//var 的情况
console.log(foo);//输出undefined
var foo = 2;
//let的情况
console.log(bar);//报错ReferenceError
let bar = 2;
3、暂时性死区
只要块级作用域内存在let命令,它所声明的变量就“绑定”这个区域,不再受外部的影响。
var tmp = 123;
if(true){
tmp = 'abc';//ReferenceError
let tmp;
}
上面的代码中存在全局变量tmp,但是在块级作用域内用let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错
- ES6明确规定,如果区块中存在let和const命令,则这个区块对这些命令声明的变量从一开始就形成封闭作用域。只要在声明之前就使用这些变量,就会报错。
- 总之在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上称为“暂时性死区”(temporal dead zone,简称TDZ)。
- "暂时性死区"也意味着typeof不再是一个百分之百安全的操作
typeof x;//ReferenceError;
let x;
上面代码中,变量x 使用let命令声明,所以在使用之前都属于x的“死区”,只要用到该变量就会报错。
作为比较,如果一个变量根本没有被声明,使用typeof反而不会被报错。
typeof undeclared_variable//"undefined"
- ES6规定暂时性死区和let、const语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。这样的错误在ES5中是很常见的,现在有了这种规定,避免这类错误就很容易了
- 总之,暂时性死区的本质就是,只要进入当前作用域,所要使用的变量就已经存在,但是不可获取,只要等到声明变量的那一行代码出现,才可以获取和使用该变量。
4、不允许重复声明
let不允许在相同作用域内重复声明同一个变量
//报错
function (){
let a = 10;
var b = 1;
}
//报错
function () {
let a = 10;
let a = 1;
}
//也不能在函数内部重新声明参数
function func (arg) {
let arg;//报错
}
function func(arg) {
{
let arg;//不报错
}
}
二、const命令
1、基本用法
- const声明一个只读的常量。一旦声明,常量的值就不能改变。
const PI = 3.1415;
PI//3.1415
PI = 3;//TypeError:Assignment to constant variable.表示改变常量的值就会报错
- const一旦声明常量,就必须立即初始化,不能留到以后赋值。
const foo;//SyntaxError:Missing initializer in const declaration表示只声明不赋值就会报错
- const的作用域与let命令相同:只在声明所在的块级作用域内有效
- const命令声明的常量也不会提升,同样存在暂时性死区,只能在声明后使用
- 也与let命令一样不可重复使用
2、本质
const实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单数据类型的数据(数值、字符串、布尔值),值就保存在变量指向的内存地址中,因此等同于常量。但对于复合类型的数据(主要是对象和数组)而言,变量指向的内存地址保存的只是一个指针,const只能保证这个指针是固定的,对于它指向的数据结构是不是可变的,这完全不能控制。