ES6学习笔记8:迭代器和for of

Iterator

Iteratior是一个可迭代对象,而for of迭代所有课迭代对象(Array, Map, Set, String, TypedArray, arguments objects等)。在JavaScript中,一个迭代器会提供一个返回序列中下一项的next()方法,该方法返回一个拥有done和value属性的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let fibonacci = {
[Symbol.iterator](){
let [pre, cur] = [0, 1];
return {
next() {
[pre, cur] = [cur, pre + cur];
return {
value: cur,
done: false
}
}
};
}
}
for (let n of fibonacci) {
if(n > 1000) {
break;
}
console.log(n);
}

注意这里创建的fibonacci对象中的[Symbol.iterator]属性,Symbol是ES6中新增的一种原始数据类型,该类型代表一个对无二的值;Symbol.iterator也是一个独一无二的值,当我们用for of去循环访问一个对象时,for of会去访问该对象的Symbol.iterator属性,该属性应该是一个对象,该对象应该有一个next()方法,next()方法经过相应逻辑处理后应该返回一个含有value和done的对象,value就是当前循环时的返回值,done表示整个循环是否结束。

for of

Map和Set是内置可迭代的,因为Map和Set的prototype都含有[Symbol.iterator]属性。

迭代Map。

1
2
3
4
5
6
7
8
9
10
11
12
13
let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]);
for (let entry of iterable) {
console.log(entry);
}
// [a, 1]
// [b, 2]
// [c, 3]
for (let [key, value] of iterable) {
console.log(value);
}
// 1
// 2
// 3

迭代Set。

1
2
3
4
5
6
7
let iterable = new Set([1, 1, 2, 2, 3, 3]);
for (let value of iterable) {
console.log(value);
}
// 1
// 2
// 3

生成器对象和生成器函数

生成器对象(Generator objects)由生成器函数(Generator function)返回。其遵从iterable协议和iterator协议。

注意生成器函数的定义形式,function关键字后面必须加*号;生成器会按照逻辑逐次生产出一个值,当一个生成器产出完所有值之后,再次尝试获取时将得到undefined。

1
2
3
4
5
6
7
8
9
10
function* gen() { 
yield 1;
yield 2;
yield 3;
}
var g = gen();
console.log(g.next().value); // 1
console.log(g.next().value); // 2
console.log(g.next().value); // 3
console.log(g.next().value); // undefined

使用for of迭代生成器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function* fibonacci() { // 生成器函数
let [prev, curr] = [1, 1];
while (true) {
[prev, curr] = [curr, prev + curr];
yield curr;
}
}
for (let n of fibonacci()) {
console.log(n);
// 在1000的位置截断序列
if (n >= 1000) {
break;
}
}

关于生成器的内容,我们将在下一篇总结中进行更深一步的探讨。

知识点总结

  1. 生成器函数和生成器对象的基本使用;
  2. for of迭代一切可迭代对象。

参考

  1. BabelJS - Learn ES2015
  2. for of - MDN
  3. generator objects - MDN
  4. generator function - MDN