[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結構
- 輸入模塊的指定方法