總結部分常用ES6的語法及其簡單解析
let/const
let/const
用於宣告變數,替代老語法的var
關鍵字,它的用法與var
類似,但是所宣告的變數只在所在的程式碼塊中有效。
let/const
與var
的主要區別:
- 不允許重複宣告
- 未定義就使用會報錯:
let/const
不存在變數提升現象 - 暫時性死區:在程式碼塊內使用
const命令
和let命令
宣告變數之前,該變數都不可用
const
與let
不相同的是,const
宣告的是一個只讀常量。
const
的特點:
const
與let
不同,const
聲明後必須立馬賦值,只宣告不賦值就會報錯const
是一個只讀常量,並不是變數的值不改變,而是變數指向的那個記憶體地址不改變。- 對於簡單型別的資料(數值、字串、布林值),就相當於常量
- 對於複合型別的資料(陣列、物件),變數指向記憶體地址,
const
實際儲存的是指向實際資料的指標,它只能保證指標不變,不能保證,指標裡的內容不變,
解構賦值
多種解構
字串解構
字串也可以解構賦值。這是因為此時,字串被轉換成了一個類似陣列的物件。
const [a, b, c, d, e] = 'hello';
數值和布林值解構
解構賦值時,如果等號右邊是數值和布林值,則會先轉為物件。
let {toString: s} = 123; s === Number.prototype.toString // true let {toString: s} = true; s === Boolean.prototype.toString // true
物件解構
物件的屬性沒有次序,變數必須與屬性同名,才能取到正確的值。
形式:const { x, y } = { x: 1, y: 2 }
預設:const { x, y = 2 } = { x: 1 }
改名:const { x, y: z } = { x: 1, y: 2 }
陣列解構
只要某種資料結構具有Iterator介面
就可採用陣列形式的解構賦值
形式:const [x, y] = [1, 2]
預設:const [x, y = 2] = [1]
函式引數解構
//陣列引數解構 function add([x, y]){ return x + y; } add([1, 2]); // 3 //物件引數解構且有預設值 function move({x = 0, y = 0} = {}) { return [x, y]; } move({x: 3, y: 8}); // [3, 8] move({x: 3}); // [3, 0] move({}); // [0, 0] move(); // [0, 0]
應用場景
-
交換變數值:
[x, y] = [y, x]
-
返回函式多個值:
const [x, y, z] = Func()
-
定義函式引數:
Func([1, 2])
-
提取JSON資料:
const { name, version } = packageJson
-
定義函式引數預設值:
function Func({ x = 1, y = 2 } = {}) {}
-
遍歷Map結構:
for (let [k, v] of Map) {}
-
輸入模組指定屬性和方法:
const { readFile, writeFile } = require("fs")
重點
- 匹配模式:只要等號兩邊的模式相同,左邊的變數就可以賦給右邊
- 解構賦值規則:只要右邊不是物件或者陣列,就會將其轉換為物件
- 解構不成功時,變數的值為
undifined
undifined
與null
無法轉為物件,因此無法賦值
箭頭函式
ES6 允許使用箭頭(=>)定義函式,簡化定義函式
var f = v => v;
// 等同於
var f = function (v) {
return v;
};
- 無引數:
() => {}
- 單個引數:
x => {}
- 多個引數:
(x, y) => {}
- 解構引數:
({x, y}) => {}
重點
-
函式體內的
this
物件,就是定義時所在的物件,而不是使用時所在的物件。 -
不可以當作建構函式,也就是說,不可以使用
new
命令,否則會丟擲一個錯誤。 -
不可以使用
arguments
物件,該物件在函式體內不存在。如果要用,可以用 rest 引數代替。
陣列的擴充套件
擴充套件運算子(...):轉換陣列為用逗號分隔的引數序列([...arr]
,相當於rest/spread引數
的逆運算)
Array.from():轉換具有Iterator介面
的資料結構為真正陣列,返回新陣列
類陣列物件:包含length的物件
、Arguments物件
、NodeList物件
可遍歷物件:String
、Set結構
、Map結構
、Generator函式
Array.of():轉換一組值為真正陣列,返回新陣列
copyWithin():把指定位置的成員複製到其他位置,返回原陣列
find():返回第一個符合條件的成員
findIndex():返回第一個符合條件的成員索引值
fill():根據指定值填充整個陣列,返回原陣列
keys():返回以索引值為遍歷器的物件
values():返回以屬性值為遍歷器的物件
entries():返回以索引值和屬性值為遍歷器的物件
陣列空位:ES6明確將陣列空位轉為undefined
(空位處理規不一,建議避免出現)
擴充套件運算子的應用
克隆陣列:const arr = [...arr1]
合併陣列:const arr = [...arr1, ...arr2]
拼接陣列:arr.push(...arr1)
代替apply:Math.max.apply(null, [x, y])
=> Math.max(...[x, y])
轉換字串為陣列:[..."hello"]
轉換類陣列物件為陣列:[...Arguments, ...NodeList]
轉換可遍歷物件為陣列:[...String, ...Set, ...Map, ...Generator]
與陣列解構賦值結合:const [x, ...rest/spread] = [1, 2, 3]
計算Unicode字元長度:Array.from("hello").length
=> [..."hello"].length
Set
- 定義:類似於陣列的資料結構,成員值都是唯一且沒有重複的值
- 宣告:
const set = new Set(arr)
- 入參:具有
Iterator介面
的資料結構 - 屬性
- constructor:建構函式,返回Set
- size:返回例項成員總數
- 方法
- add():新增值,返回例項
- delete():刪除值,返回布林
- has():檢查值,返回布林
- clear():清除所有成員
- keys():返回以屬性值為遍歷器的物件
- values():返回以屬性值為遍歷器的物件
- entries():返回以屬性值和屬性值為遍歷器的物件
- forEach():使用回撥函式遍歷每個成員
應用場景
- 去重字串:
[...new Set(str)].join("")
- 去重陣列:
[...new Set(arr)]
或Array.from(new Set(arr))
- 集合陣列
- 宣告:
const a = new Set(arr1)
、const b = new Set(arr2)
- 並集:
new Set([...a, ...b])
- 交集:
new Set([...a].filter(v => b.has(v)))
- 差集:
new Set([...a].filter(v => !b.has(v)))
- 宣告:
- 對映集合
- 宣告:
let set = new Set(arr)
- 對映:
set = new Set([...set].map(v => v * 2))
或set = new Set(Array.from(set, v => v * 2))
- 宣告:
重點難點
- 遍歷順序:插入順序
- 沒有鍵只有值,可認為鍵和值兩值相等
- 新增多個
NaN
時,只會存在一個NaN
- 新增相同的物件時,會認為是不同的物件
- 新增值時不會發生型別轉換(
5 !== "5"
) keys()
和values()
的行為完全一致,entries()
返回的遍歷器同時包括鍵和值且兩值相等
WeakSet
- 定義:和Set結構類似,成員值只能是物件
- 宣告:
const set = new WeakSet(arr)
- 入參:具有
Iterator介面
的資料結構 - 屬性
- constructor:建構函式,返回WeakSet
- 方法
- add():新增值,返回例項
- delete():刪除值,返回布林
- has():檢查值,返回布林
應用場景
- 儲存DOM節點:DOM節點被移除時自動釋放此成員,不用擔心這些節點從文件移除時會引發記憶體洩漏
- 臨時存放一組物件或存放跟物件繫結的資訊:只要這些物件在外部消失,它在
WeakSet結構
中的引用就會自動消
重點難點
- 成員都是
弱引用
,垃圾回收機制不考慮WeakSet結構
對此成員的引用 - 成員不適合引用,它會隨時消失,因此ES6規定
WeakSet結構不可遍歷
- 其他物件不再引用成員時,垃圾回收機制會自動回收此成員所佔用的記憶體,不考慮此成員是否還存在於
WeakSet結構
中
Map
- 定義:類似於物件的資料結構,成員鍵是任何型別的值
- 宣告:
const set = new Map(arr)
- 入參:具有
Iterator介面
且每個成員都是一個雙元素陣列的資料結構 - 屬性
- constructor:建構函式,返回Map
- size:返回例項成員總數
- 方法
- get():返回鍵值對
- set():新增鍵值對,返回例項
- delete():刪除鍵值對,返回布林
- has():檢查鍵值對,返回布林
- clear():清除所有成員
- keys():返回以鍵為遍歷器的物件
- values():返回以值為遍歷器的物件
- entries():返回以鍵和值為遍歷器的物件
- forEach():使用回撥函式遍歷每個成員
重點難點
- 遍歷順序:插入順序
- 對同一個鍵多次賦值,後面的值將覆蓋前面的值
- 對同一個物件的引用,被視為一個鍵
- 對同樣值的兩個例項,被視為兩個鍵
- 鍵跟記憶體地址繫結,只要記憶體地址不一樣就視為兩個鍵
- 新增多個以
NaN
作為鍵時,只會存在一個以NaN
作為鍵的值 Object結構
提供字串—值
的對應,Map結構
提供值—值
的對應
WeakMap
- 定義:和Map結構類似,成員鍵只能是物件
- 宣告:
const set = new WeakMap(arr)
- 入參:具有
Iterator介面
且每個成員都是一個雙元素陣列的資料結構 - 屬性
- constructor:建構函式,返回WeakMap
- 方法
- get():返回鍵值對
- set():新增鍵值對,返回例項
- delete():刪除鍵值對,返回布林
- has():檢查鍵值對,返回布林
應用場景
- 儲存DOM節點:DOM節點被移除時自動釋放此成員鍵,不用擔心這些節點從文件移除時會引發記憶體洩漏
- 部署私有屬性:內部屬性是例項的弱引用,刪除例項時它們也隨之消失,不會造成記憶體洩漏
重點難點
- 成員鍵都是
弱引用
,垃圾回收機制不考慮WeakMap結構
對此成員鍵的引用 - 成員鍵不適合引用,它會隨時消失,因此ES6規定
WeakMap結構不可遍歷
- 其他物件不再引用成員鍵時,垃圾回收機制會自動回收此成員所佔用的記憶體,不考慮此成員是否還存在於
WeakMap結構
中 - 一旦不再需要,成員會自動消失,不用手動刪除引用
- 弱引用的
只是鍵而不是值
,值依然是正常引用 - 即使在外部消除了成員鍵的引用,內部的成員值依然存在
Promise
- 定義:Promise是一種非同步程式設計的解決方案。從語法上來講,Promise是一個物件,他可以獲取非同步操作的的訊息。從本意上來講,Promise是一個承諾,承諾過一段時間後給你一個結果。Promise有三種狀態:pending(等待),fulfiled(成功),rejected(失敗),狀態一旦改變,就不會再變。
- 狀態:
- 進行中:pending
- 已成功:fulfilled
- 已失敗:rejected
- 特點:
- 物件的操作不受外界的影響
- 一旦狀態改變,任何時候都會得到這個結果
- 示例:
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 非同步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
-
出參
- resolve:將狀態從
未完成
變為成功
,在非同步操作成功時呼叫,並將非同步操作的結果作為引數傳遞出去 - reject:將狀態從
未完成
變為失敗
,在非同步操作失敗時呼叫,並將非同步操作的錯誤作為引數傳遞出去
- resolve:將狀態從
-
方法:
-
then():分別指定
resolved
和rejected
狀態的回撥函式- 第一引數:狀態變為
resolved
時呼叫 - 第二引數:狀態變為
rejected
時呼叫
- 第一引數:狀態變為
-
catch():用於指定發生錯誤時的回撥函式。
-
Promise.all():將多個例項包裝成一個新例項,返回全部例項狀態變更後的結果陣列(齊變更再返回)
- 入參:具有
Iterator介面
的資料結構 - 成功:只有全部例項狀態變成
fulfilled
,最終狀態才會變成fulfilled
- 失敗:其中一個例項狀態變成
rejected
,最終狀態就會變成rejected
- 入參:具有
-
Promise.race():將多個例項包裝成一個新例項,返回全部例項狀態優先變更後的結果(先變更先返回)
- 入參:具有
Iterator介面
的資料結構 - 成功失敗:哪個例項率先改變狀態就返回哪個例項的狀態
- 入參:具有
-
Promise.resolve():將物件轉為Promise物件(等價於
new Promise(resolve => resolve())
)- Promise例項:原封不動地返回入參
- Thenable物件:將此物件轉為Promise物件並返回(Thenable為包含
then()
的物件,執行then()
相當於執行此物件的then()
) - 不具有then()的物件:將此物件轉為Promise物件並返回,狀態為
resolved
- 不帶引數:返回Promise物件,狀態為
resolved
-
Promise.reject():將物件轉為狀態為
rejected
的Promise物件(等價於new Promise((resolve, reject) => reject())
)
-
應用場景
-
載入圖片
-
AJAX轉Promise物件
重點難點
-
只有非同步操作的結果可決定當前狀態是哪一種,其他操作都無法改變這個狀態
-
狀態改變只有兩種可能:從
pending
變為resolved
、從pending
變為rejected
-
一旦新建
Promise物件
就會立即執行,無法中途取消 -
不設定回撥函式,內部拋錯不會反應到外部
-
當處於
pending
時,無法得知目前進展到哪一個階段 -
例項狀態變為
resolved
或rejected
時,會觸發then()
繫結的回撥函式 -
resolve()
和reject()
的執行總是晚於本輪迴圈的同步任務 -
then()
返回新例項,其後可再呼叫另一個
then() -
then()
執行中丟擲錯誤會被catch()
捕獲 -
reject()
的作用等同於丟擲錯誤 -
例項狀態已變成
resolved
時,再丟擲錯誤是無效的,不會被捕獲,等於沒有丟擲 -
例項狀態的錯誤具有
冒泡
性質,會一直向後傳遞直到被捕獲為止,錯誤總是會被下一個catch()
捕獲 -
不要在
then()
裡定義rejected
狀態的回撥函式(不使用其第二引數) -
建議使用
catch()
捕獲錯誤,不要使用then()
第二個引數捕獲 -
沒有使用
catch()
捕獲錯誤,例項拋錯不會傳遞到外層程式碼,即不會有任何反應
-
作為引數的例項定義了
catch()
,一旦被rejected
並不會觸發Promise.all()
的catch()
-
Promise.reject()
的引數會原封不動地作為rejected
的理由,變成後續方法的引數
for...of
迴圈
-
定義:呼叫
Iterator
介面產生遍歷器物件(for-of
內部呼叫資料結構的Symbol.iterator()
) -
遍歷字串:
for-in
獲取索引
,for-of
獲取值
. -
遍歷陣列:
for-in
獲取索引
,for-of
獲取值
-
遍歷Set:
for-of
獲取值
=>for (const v of set)
-
遍歷Map:
for-of
獲取鍵值對
=>for (const [k, v] of map)
,for-of
獲得到的是一個由鍵
與值
構成的陣列let map = new Map().set('a', 1).set('b', 2); for (let pair of map) { console.log(pair); } // ['a', 1] // ['b', 2] for (let [key, value] of map) { console.log(key + ' : ' + value); } // a : 1 // b : 2
-
遍歷物件:
for-in
獲取鍵
,for-of
需自行部署for-of
並不能直接遍歷物件,如果直接遍歷會報錯。我們需要部署Iterator
介面。遍歷物件還是使用for-in
更好一點- 使用
Object.keys
方法將物件的鍵名生成一個數組,然後遍歷這個陣列。
for (var key of Object.keys(someObject)) { console.log(key + ': ' + someObject[key]); }
- 使用 Generator 函式將物件重新包裝一下。
function* entries(obj) { for (let key of Object.keys(obj)) { yield [key, obj[key]]; } } for (let [key, value] of entries(obj)) { console.log(key, '->', value); } // a -> 1 // b -> 2 // c -> 3
- 使用
-
與
for-in
區別- 有著同
for-in
一樣的簡潔語法,但不會像for-in
一樣會遍歷原型上的屬性。 for-of
會以新增順序來進行遍歷,而不會像for-in
以任意順序遍歷- 不同於
forEach()
,它可與break
、continue
和return
配合使用 - 提供遍歷所有資料結構的統一操作介面
- 有著同