JavaScript的Iterator和Generator
1. Iterator
ES6 中,默认的 Iterator
接口部署在数据结构的 Symbol.iterator
属性。一个数据结构只要拥有 Symbol.iteration
属性,就是可遍历的。Symbol.iterator
是一个函数,返回当前数据结构的遍历器。Iterator
提供了 next()
方法用以返回迭代器结果对象。
let arr = ["a", "b", "c"];
// 获取数组的Iterator
let symbolIterator = arr[Symbol.iterator]();
// 遍历数组
let value = symbolIterator.next();
while (value.value) {
console.log(value.value);
value = symbolIterator.next();
}
1.2 for-of语法糖
拥有 Symbol.iteration
属性的数据结构,可以通过 for-of 遍历。
- Array
- Set
- Map
- String
- arguments 对象
- NodeList 对象
function test(param1, param2) {
// 函数体内都有一个arguments对象,装着所有参数
for (param of arguments) {
console.log(param)
}
}
test(1, 2);
2. Generator
Generator
对象由生成器函数
返回。Generator
是隐藏类 Iterator
的子类。
2.1 定义一个生成器函数
// 与定义普通函数的不同在于:function关键字后面跟一个*
function* generator() {
}
// 调用生成器函数,只是进行实例化,并不执行函数体的代码
let iterator = generator();
2.2 常用的方法
- next():返回
yield
表达式生成的值。 - return():类似于在当前的生成器主体的暂停位置插入
return
语句 - throw():类似于在当前的生成器主体的暂停位置插入
throw
语句
2.3 基本用法
// 定义一个 Generator 函数
function* generator() {
console.log("a");
// yield 表达式
yield 1;
console.log("b");
yield 2;
console.log("c");
}
// 调用生成器函数,只是进行实例化,并不执行函数体的代码
let iterator = generator();
// 调用 next() 开始执行函数体的代码,遇到 yield 停止执行,并返回 yield 表达式生成的值
// yield 表达式返回的是一个对象,包含 value 和 done 两个属性
let result1 = iterator.next();
console.log(result1.value);
// 再调用 next(),继续执行,遇到 yield 停止执行
let result2 = iterator.next();
console.log(result2.value);
// 再调用 next(),继续执行
iterator.next();
2.4 传参的用法
// 定义一个 Generator 函数
function* generator() {
console.log("a");
// yield表达式前面的变量param1,用来接收next()传递的参数
let param1 = yield 1;
console.log(param1);
let param2 = yield 2;
console.log(param2);
}
let iterator = generator();
// 第一个 next() 在遇到 yield 就停止了,此时 next() 传递的参数还没有赋值给变量 param1,并且该参数会被丢失
let result1 = iterator.next("x");
console.log(result1.value);
// 第二个 next() 让代码继续执行,先把参数赋值给 param1
let result2 = iterator.next("y");
console.log(result2.value);
iterator.next("z");
2.5 异步的用法
// 定义一个异步的生成器函数
async function* generator() {
yield new Promise( (resolve, reject) => {
// 进行异步操作
setTimeout( () => {
resolve("1000ms");
}, 1000);
} );
yield new Promise( (resolve, reject) => {
// 进行异步操作
setTimeout( () => {
resolve("2000ms");
}, 2000);
} );
}
let iterator = generator();
// async 返回的是一个promise,可以采用链式调用
// data 是一个对象,包含 value 和 done 两个属性
iterator.next().then((data) => {
console.log(data);
return iterator.next();
}).then((data) => {
console.log(data);
return iterator.next();
}).then((data) => {
console.log(data);
return iterator.next();
}).catch((err) => {
console.log(err);
});