[toc]
## 1. let
let命令用于声明变量,与var类似,但是只在let命令所在的代码块内有效。
let命令不存在变量提升,但是会产生暂时性死区(temporal dead zone),暂时性死区是一个封闭作用域。如果区块中存在let和const命令,则这个区块对这些命令声明的变量从一开始就形成封闭作用域。
```js
var tmp = 123;
if(true){
tmp = "a"; //出错,因为位于代码块内存在let命令,并且没有进行变量提升
let tmp;
}
```
let命令不允许重复声明,也就是不允许在相同的作用域内重复声明一个变量。
在ES5中只存在全局作用域和函数作用域,而ES6新添加了块级作用域。
## 2. const
const命令用于声明一个常量。使用const声明的常量不能改变其值,因此声明时必须初始化,否则会出错。
要注意变量的类型,如果声明的是一个引用类型常量,则不可改变的是该常量指向的地址,但是常量本身可以修改。
```
const foo = {};
foo.prop = 3;
foo.prop; //3
foo = {}; //出错,企图将foo指向一个新的对象
```
如果需要将一个对象冻结,则使用Object.freeze()方法。
## 3. 解构赋值
### 数组的解构赋值
```
var [a,b,c] = [1,2,3];
//等价于
var a = 1;
var b = 2;
var c = 3;
```
解构赋值本质上相当于"模式匹配",只要两边模式相同,就能将右边的值赋给左边的变量。同样也支持嵌套解构
```
let [foo,[bar],baz] = [1,[[2],3]]
foo //1
bar //2
baz //3
```
```
let [head,...tail] = [1,2,3,4];
head //1
tail //[2,3,4]
```
不完全解构
```
var [foo,baz] = [1];
foo // 1
baz //undefined
var [x,y] = [1,2,3]
x //1
y //2
//3抛弃
```
解构赋值可以指定默认值
```
var [x,y="b"] = ["a"]; //x="a",y="b"
var [x=1] = [null]; //x=null
```
在解构赋值时之后右边对应的位置值严格等于undefined时,左边的变量才会取默认值,null不严格等于undefined
### 对象的解构赋值
准确来说,凡是可以迭代的都可以进行解构赋值,比如数组,对象,字符串等
在对对象进行解构赋值时,并不是按照顺序进行的,而是按照属性名。
```
var {bar,foo} = {foo:"aaa",bar:"bbb"}; //foo等于aaa,bar等于bbb,不受属性顺序的影响
var {bar} = {baz:"ccc"}; //bar等于undefined
```
对象解构赋值的完整形式
```
var {a:b} = {a:1}
```
a表示模式,用来从右边获取值,b才是定义的承接值得变量,在上述例子中,实际上是{bar:bar,foo:foo}的简写
与数组一样,对象的解构也可以用以嵌套结构
```
var obj = {
p:[
"hello",
{y:"world"}
]
};
var {p:[x,{y}]} = obj; //x等于hello,y等于world
//注意p表示模式,不承接值
```
解构赋值的作用
- 交换变量
- 从函数返回多个值
- 定义为函数的参数
- 提取JSON
- 函数参数默认值
- 遍历Map结构
- 输入模块的指定方法