迭代器
迭代器是被设计专用于迭代的对象,带有特定接口。所有的迭代器对象都拥有next()方法,会返回一个结果对象。该结果对象有两个属性:对应下一个值的value,以及一个布尔类型的done,其值为true时表示没有更多值可供使用。迭代器持有一个指向集合位置的内部指针,每当调用了next()方法,迭代器就会返回相应的下一个值。
使用es5模拟一个迭代器
function createIterator(items) {
var i = 0
// 返回一个迭代器对象
return {
next: () => {
var done = i >= items.length
var value = !done ? items[++i] : undefined
return {
done,
value
}
}
}
}
var list = createIterator([1, 2, 3, 4, 5])
console.log(list.next()) // { done: false, value: 2 }
console.log(list.next()) // { done: false, value: 3 }
console.log(list.next()) // { done: false, value: 4 }
console.log(list.next()) // { done: false, value: 5 }
console.log(list.next()) // { done: true, value: undefined }
生成器
生成器(generator)是能返回一个迭代器的函数。生成器函数由放在function关键字之后的一个星号(*)来表示,并能使用新的yield关键字。将星号紧跟在function关键字之后,或是在中间留出空格,都是没问题的。
function *createIterator() {
yield 1
yield 2
yield 3
}
let iterator = createIterator()
console.log(iterator.next().value) // 1
console.log(iterator.next().value) // 2
console.log(iterator.next().value) // 3
可迭代对象与 for-of 循环
与迭代器紧密相关的是,可迭代对象(iterable)是包含Symbol.iterator属性的对象。这个Symbol.iterator知名符号定义了为指定对象返回迭代器的函数。在 ES6 中,所有的集合对象(数组、 Set 与 Map )以及字符串都是可迭代对象,因此它们都被指定了默认的迭代器。
for-of循环在循环每次执行时会调用可迭代对象的next()方法,并将结果对象的value值存储在一个变量上。循环过程会持续到结果对象的done属性变成true为止。
let value = [1, 2, 3]
for (let num of value) {
console.log(num)
}
输出:
1
2
3
访问默认迭代器 Symbol.iterator
let values = [1, 2, 3, 4, 5]
let iterator = values[Symbol.iterator]()
iterator.next() // {value: 1, done: false}
iterator.next() // {value: 2, done: false}
iterator.next() // {value: 3, done: false}
集合的迭代器
ES6 具有三种集合对象类型:数组、 Map 与 Set 。
- entries():返回一个包含键值对的迭代器;
- values():返回一个包含集合中的值的迭代器;
- keys():返回一个包含集合中的键的迭代器。
let map = new Map([['name', 'age'], ['map', 5]])
map.entries() // MapIterator {"name" => "age", "iterator" => 5, "friends" => "none"}
map.values() // MapIterator {"map", 5}
map.keys() // MapIterator {"name", "age"}
let set = new Set([1, 2, 3, 4, 5])
set.entries() // SetIterator {1 => 1, 2 => 2, 3 => 3}
set.values() // SetIterator {1, 2, 3, 4, 5}
set.keys() // SetIterator {1, 2, 3, 4, 5}
let arr = [1, 2, 3, 4, 5]
arr.entries() // Array Iterator {}
arr.values() // Array Iterator {}
arr.keys() // Array Iterator {}
调用迭代器方法返回的数据需要通过 for...of... 来遍历
字符串的迭代器
从 ES5 发布开始, JS 的字符串就慢慢变得越来越像数组。例如 ES5 标准化了字符串的方括号表示法,用于访问其中的字符(即:使用text[0]来获取第一个字符,以此类推)。
所以也可以像遍历集合那样遍历字符串
- 传统 for 循环
- for...of...
NodeList 的迭代器
文档对象模型( DOM )具有一种NodeList类型,用于表示页面文档中元素的集合。NodeList对象与数组都使用了length属性来标明项的数量,并且都使用方括号表示法来访问各个项。然而本质上来说,NodeList与数组的行为是完全不同的,这会引发许多混乱。
着默认迭代器被附加到 ES6 , DOM 关于NodeList的规定也包含了一个默认迭代器(此规定在 HTML 规范而非 ES6 规范中),其表现方式与数组的默认迭代器一致。这意味着你可以将NodeList用于for-of循环,或用于其他使用对象默认迭代器的场合。
let divs = document.getElementsByTagName("div")
for (let div of divs) {
console.log(div.id)
}