迭代器和生成器
迭代器
迭代器基础
常见迭代器类型
- Strings;
- Arrays;
- Maps;
- Sets;
- The arguments object;
- DOM collection types;
常见迭代操作
let arr = ["foo", "bar", "baz"];
// for...of loops
for (let el of arr) {
console.log(el);
}
// Array destructuring
let [a, b, c] = arr;
console.log(a, b, c); // foo, bar, baz
// Spread operator
let arr2 = [...arr];
console.log(arr2); // ['foo', 'bar', 'baz']
// Array.from()
let arr3 = Array.from(arr);
console.log(arr3); // ['foo', 'bar', 'baz']
// Set constructor
let set = new Set(arr);
console.log(set); // Set(3) {'foo', 'bar', 'baz'}
// Map constructor
let pairs = arr.map((x, i) => [x, i]);
console.log(pairs); // [['foo', 0], ['bar', 1], ['baz', 2]]
let map = new Map(pairs);
console.log(map); // Map(3) { 'foo'=>0, 'bar'=>1, 'baz'=>2 }
常用 API
迭代
let arr = ["foo", "bar"];
// 访问迭代器
let iter = arr[Symbol.iterator]();
// 迭代器默认为空
console.log(iter); // ArrayIterator {}
// 返回 iterator 的下一个元素 {done, value}
// done 表示是否到达终点, value 对应值
console.log(iter.next()); // { done: false, value: 'foo' }
console.log(iter.next()); // { done: false, value: 'bar' }
console.log(iter.next()); // { done: true, value: undefined }
迭代器进阶
自定义迭代器
- 使用 Symbol.iterator 属性实现迭代器;
- 必须实现 next 方法;
- 返回包括 value 和 done 两属性的对象;
- value:当前值;
- done:是否迭代完成;
class Counter {
constructor(limit) {
this.limit = limit;
}
[Symbol.iterator]() {
let count = 1,
limit = this.limit;
return {
next() {
if (count <= limit) {
return { done: false, value: count++ };
} else {
return { done: true, value: undefined };
}
},
};
}
}
let counter = new Counter(3);
for (let i of counter) {
console.log(i);
}
// 1
// 2
// 3
关闭迭代器
- 定义 return 方法手动关闭迭代器;
- for。。.of 中使用 continue,break,return,throw 会触发 return();
class Counter {
constructor(limit) {
this.limit = limit;
}
[Symbol.iterator]() {
let count = 1,
limit = this.limit;
return {
next() {
if (count <= limit) {
return { done: false, value: count++ };
} else {
return { done: true };
}
},
return() {
console.log("Exiting early");
return { done: true };
},
};
}
}
let counter1 = new Counter(5);
for (let i of counter1) {
if (i > 2) {
break;
}
console.log(i);
}
// 1
// 2
// Exiting early
未 return() 方法
- 可以继续从上次离开的地方继续迭代;
let a = [1, 2, 3, 4, 5];
let iter = a[Symbol.iterator]();
for (let i of iter) {
console.log(i);
if (i > 2) {
break;
}
}
// 1
// 2
// 3
for (let i of iter) {
console.log(i);
}
// 4
// 5
如何检测 iterator 是否可以停止
- 检测 iterator 是否具有 return 属性且是否为函数对象