簡介
在很多流行的編程語言裏,都有解構賦值的概念,比如Perl
,Python
ES6中也加入了類似的賦值語句,比以前的賦值操作更靈活,更快捷
正文
數組的解構賦值很好理解,就是按照對應位置,對變量賦值:
let [a, b, c] = [1, 2, 3]
相當於
let a = 1
let b = 2
let c = 3
支持數組嵌套,也支持等號兩邊結構不同的情況
如果變量對應不上值,這個變量就是undefined,如果一個值對應不到變量,那這個值被忽略
[a, b, c] = [1, 2]
// a,b爲1,2 c由於匹配不到爲undefined
[a, b] = [1, 2, 3]
// a,b爲1,2 3由於沒有變量接收被忽略
基於解構賦值,函數也可以有多個返回值了:
function tuple() {
return [1, 2]
}
let [first, second] = tuple()
解構賦值允許指定默認值,也允許使用rest參數(...
)來接收不確定個數的參數:
let [firstName = "John", lastName = "Doe"] = []
let [a, b, ...rest] = [1, 2, 3, 4, 5]
a // 1
b // 2
rest // [3, 4, 5]
與函數的rest參數一樣,rest後面不允許再有其他參數了
對象的解構賦值與數組類似,只有在屬性名對應相同的情況下,右側屬性的值會被賦值給左側對應屬性的值
let {firstName: name, lastName} = {firstName: "John", lastName: "Doe"}
name // "John"
lastName // "Doe"
firstName // Uncaught ReferenceError: firstName is not defined
注意被賦值的是同名屬性的值,這裏是name 而不是firseName
lastName被賦值成功是因爲這是變量的簡潔表示法,忘記了的回去看對象一節
其實數組可以看做屬性名都是自然數的對象:
let {"0": a, "1": b} = {"0": 1, "1": 2}
a // 1
b // 2
這樣看起來會更好的理解對象的解構賦值,實際上行爲與數組的解構賦值是一致的
思考
這部分內容希望你都可以手動敲一遍,獨立思考
試着用解構賦值去交換兩個變量的值
如果不使用解構賦值,如何交換兩個變量的值呢?
let [a = 1] = [undefined]
let [b = 1] = [null]
上面代碼中的a, b分別是什麼?試着自己解釋這個結果
let [x = y, y = 1] = []
上面代碼的結果是什麼? 爲什麼?
ES6中新增了一種遍歷語法:for (... of ...)
來支持所有可遍歷的數據結構
for-of
是基於iterator
這個通用接口實現的
正文
在ES6以前,我們想遍歷一個數組一般有三種方式:
for
循環for ... in
語句Array.prototype.forEach
方法
三種方式都有不同程度的缺陷
for
循環寫法繁瑣,需要指定循環次數不超過數組長度,否則就會有對應的報錯
for ... in
語句遍歷出的是鍵值,需要做一些轉換才能拿到數據,而且遍歷是無序的
forEach
方法是個不錯的方式,不過它不能中途使用break
跳出循環,也不能return
終止外層函數
基於這些缺陷,ES6新增了 for ... of
的語法,用於遍歷數組,對象,字符串,或者是Set
,Map
等數據結構
for ... of
遍歷依賴 iterator
接口,只有部署了 iterator
接口的數據類型纔可以被遍歷
iterator 接口是這些數據結構上的一個屬性:Symbol.iterator
,它是一個函數
let iterator = [1, 2, 3][Symbol.iterator]()
iterator // Array Iterator {}
iterator.next()
// {value: 1, done: false}
iterator.next()
// {value: 2, done: false}
iterator.next()
// {value: 3, done: false}
iterator.next()
// {value: undefined, done: true}
Symbol.iterator顯然是一個Symbol類型值,在Symbol章節介紹過,必須使用方括號訪問
調用數組上的 Symbol.iterator 方法,即可返回一個iterator遍歷器對象
這個 iterator 對象上只有一個常用方法 next
,每次調用 next
即可返回一個對象
返回的對象有兩個屬性,value :當前遍歷的值, done :是否遍歷完畢
這裏必須說明一下爲什麼這個遍歷器的屬性名是一個很繞的Symbol類型
其實最開始是打算叫做 iterator()
的 ,可是考慮到已有的代碼中,可能已經有人用這個名字命名了一些屬性
ES6如果直接使用這個名字會造成兼容性問題,無奈之下只能使用絕對不可能重複的 [Symbol.iterator]()
for…of 語句會在內部直接調用遍歷對象上的 Symbol.iterator
方法
並且每次循環中自動調用返回值的next方法,然後將next方法返回值的value屬性值賦值給每次的循環變量
for (let a of arr){
console.log(a)
}
// 1 2 3
正常情況下我們不會手動使用next方法去一個一個的拿到值
而是使用 for … of 方便的遍歷所有具有 Symbol.iterator
屬性的對象
思考
這部分內容希望你都可以手動敲一遍,獨立思考
let map = new Map([
['a', '1'],
['b', '2']
])
for (let a of map){
console.log(a)
}
上面代碼的輸出結果會是什麼?
如果想要每次只輸出map
中每一項對應的值,應該怎麼改寫?
試着根據上面描述的for ... of
實現方法,自己動手實現一個具有for ... of
功能的function
接收一個可遍歷對象,並向命令行依次輸出遍歷結果