# 迭代器与生成器
# 1、迭代器原理
可迭代对象指的是任何具有专用迭代器方法,且该方法返回迭代器对象的对象。迭代器对象指的是任何具有 next()方法,且该方 法返回迭代结果对象的对象。迭代结果对象是具有属性 value 和 done 的对象。
要迭代一个可迭代对象,首先要调用其迭代器方法获得一个迭代器对象。然后,重复调用这个迭代器对象的 next()方法,直至返回 done 属性为 true 的迭代结果对象。
可迭代对象的迭代器方法没有使用惯用名称,而是使用了符号 Symbol.iterator 作为名字。
const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();
for (let i of iterator) {
console.log(i);
}
// 1
// 2
// 3
// 执行迭代
console.log(iter.next()); // { done: false, value: 1 }
console.log(iter.next()); // { done: false, value: 2 }
console.log(iter.next()); // { done: false, value: 3 }
console.log(iter.next()); // { done: true, value: undefined }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 2、实现可迭代对象
class Foo {
[Symbol.iterator]() {
return {
next() {
return { done: false, value: 'foo' };
},
// 指定在迭代器提前关闭时执行的逻辑
return() {
console.log('early end');
return { done: true };
},
// 让迭代器本身也可迭代
[Symbol.iterator]() {
return this;
},
};
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 3、生成器
function* gFn() {
yield 1;
yield 2;
yield 3;
}
// 调用生成器函数,得到一个生成器
const g = gFn();
g.next(); // 1
g.next(); // 2
g.next(); // 3
// 在类和字面量中简写
const o = {
x: 1,
y: 2,
*g() {
yield 3;
yield 4;
},
};
[...o.g()] // => [3, 4]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
注意,不能使用箭头函数语法定义生成器函数。
# 3.1 生成器函数的返回值
function* oneAndDone() {
yield 1;
return 'done';
}
// 正常迭代中不会出现的返回值
[...oneAndDone()] // => [1]
// 显式调用 next() 可以得到
const g = oneAndDone()
g.next() // => { value: 1, done: false }
g.next() // => { value: 'done', done: true }
g.next() // => { value: undefined, done: true }
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 3.2 yield 表达式的值
yield是一个表达式(回送表达式),可以有值
function* smallNum() {
console.log('第一次调用,参数被丢弃')
const y1 = yield 1; // y1 === 'b'
console.log('第二次调用,参数是', y1)
const y2 = yield 2; // y1 === 'c'
console.log('第三次调用,参数是', y2)
const y3 = yield 3; // y1 === 'd'
console.log('第四次调用,参数是', y3)
return 4;
}
const g = smallNum()
console.log('创建了生成器,代码未运行')
const n1 = g.next('a') // n1.value === 1
console.log('生成器回送', n1.value)
const n2 = g.next('b') // n2.value === 2
console.log('生成器回送', n2.value)
const n3 = g.next('c') // n3.value === 3
console.log('生成器回送', n3.value)
const n4 = g.next('d') // n4.value === { value: 4, done: true }
console.log('生成器回送', n4.value)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
注意以上代码是不对称的。第一次调用next()启动生成器,但传入的值无法在生成器中访问到。