Symbol.iterator
ECMAScript 2015的幾個(gè)補(bǔ)充,并不是新的內(nèi)置實(shí)現(xiàn)或語法,而是協(xié)議。這些協(xié)議可以被任何遵循某些約定的對(duì)象來實(shí)現(xiàn)。
ES6新增了兩個(gè)協(xié)議:
- 可迭代協(xié)議:對(duì)象必須具有Symbol.Iterator屬性,屬性值為一個(gè)函數(shù),當(dāng)這個(gè)對(duì)象被迭代時(shí),就會(huì)調(diào)用該函數(shù),返回一個(gè)迭代器。
- 迭代器協(xié)議:描述了迭代器對(duì)象的具體規(guī)則。
what
- 在Js中迭代器對(duì)象實(shí)現(xiàn)了可迭代協(xié)議,迭代器對(duì)象由Symbol.iterator屬性的值返回。
- Symbol.iterator屬性的值是一個(gè)函數(shù),它返回一個(gè)迭代器對(duì)象。
- 迭代器指的是擁有next方法的對(duì)象。
- 該next方法必須返回一個(gè)帶有value和done的對(duì)象。
why
除了Array和Object,ES6新增了數(shù)據(jù)結(jié)構(gòu)Set、Map,這樣的話,JS中就有了四種表示集合的數(shù)據(jù)結(jié)構(gòu)。這時(shí),js就需要一種統(tǒng)一的用來遍歷這些集合的接口。迭代器Iterator就是這個(gè)接口,具體表現(xiàn)在各數(shù)據(jù)結(jié)構(gòu)的Symbol.Iterator屬性上。
注意:對(duì)象Object沒有這個(gè)接口,因?yàn)閷?duì)象是非線性的數(shù)據(jù)結(jié)構(gòu),一旦部署這個(gè)接口相當(dāng)部署一種線性轉(zhuǎn)換。
how
1.數(shù)據(jù)結(jié)構(gòu)默認(rèn)的Iterator接口,可以通過for...of使用。解構(gòu)賦值用的也是Iterator接口。
let obj = {
[Symbol.iterator] () {
let val = 0
return {
next () {
if (val > 5) {
return {done: true}
}
return {value: val++,done: false}
}
}
}
}
for (let val of obj) {console.log(val)}
let iterator = obj[Symbol.iterator]
iterator.next()
iterator.next()
iterator.next()
iterator.next()
iterator.next()
iterator.next()
2.使用generator函數(shù)
let obj = {
[Symbol.iterator]: function* () {
yield 1;
yield 2;
yield 3;
}
}
for (let val of obj) {console.log(val)}
which
下面這些數(shù)據(jù)結(jié)構(gòu)默認(rèn)實(shí)現(xiàn)了迭代器接口
- 字符串
- 數(shù)組
- Map
- Set
- NodeList
- arguments
- TypedArray
for...of
what
for...of語法借鑒自C++、Java、C# 和 Python,作為用來遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一方法。
why
和迭代器一起設(shè)計(jì),迭代器主要供for...of消費(fèi)
how
let arr = ['a', 'b', 'c'];
for (let pair of arr) {
console.log(pair);
}
for (let pair of arr.entries()) {
console.log(pair);
}
for (let pair of arr.keys()) {
console.log(pair);
}
for (let pair of arr.values()) {
console.log(pair);
}
compare
for的缺陷:
// 取值比較麻煩
for (var index = 0; index < myArray.length; index++) {
console.log(myArray[index]);
}
為了解決for麻煩的問題,引入的forEach
// 問題:無法跳出循環(huán)
myArray.forEach(function (value) {
console.log(value);
});
for...in的缺陷:
1. 會(huì)遍歷所有可枚舉的屬性,包括原型鏈(是否可遍歷只和該對(duì)象上的屬性enumerable有關(guān),和在哪里無關(guān))
2. 除了數(shù)組中的元素,會(huì)遍歷數(shù)組的私有屬性
3. 專門為對(duì)象設(shè)計(jì)
var a = []
Object.getOwnPropertyDescriptor(a.__proto__,'find') // false 這些原生方法默認(rèn)enumerable為false