迭代器是一种用于遍历数据集合的对象,ES6 中引入了生成器函数(Generator Function)来方便地生成迭代器。ES12 中进一步增强了生成器函数的功能,本文将介绍 ES12 生成迭代器的基础知识和用法。
生成器函数回顾
在 ES6 中,我们可以使用生成器函数来创建迭代器,生成器函数是一种特殊的函数,使用 function*
关键字定义,其中使用 yield
关键字可以暂停函数的执行并返回一个值,下次调用函数时从上次暂停的位置继续执行。
以下是一个简单的生成器函数示例:
// javascriptcn.com 代码示例 function* myGenerator() { yield 1; yield 2; yield 3; } const iterator = myGenerator(); console.log(iterator.next()); // { value: 1, done: false } console.log(iterator.next()); // { value: 2, done: false } console.log(iterator.next()); // { value: 3, done: false } console.log(iterator.next()); // { value: undefined, done: true }
可以看到,我们通过 function*
定义了一个生成器函数 myGenerator
,其中使用 yield
关键字返回了三个值。我们通过 myGenerator()
调用生成器函数并得到一个迭代器对象 iterator
,然后使用 next()
方法遍历迭代器,每次调用都会返回一个包含当前值和是否遍历结束的对象。
生成器函数的新特性
在 ES12 中,生成器函数得到了进一步增强,以下是新增的特性:
1. 生成器函数可以使用 return
关键字返回值
在 ES6 中,生成器函数只能通过 yield
关键字返回值,如果使用 return
关键字会导致函数立即结束。但是在 ES12 中,生成器函数可以使用 return
关键字返回值,并且会立即结束函数的执行。
以下是一个使用 return
关键字的示例:
// javascriptcn.com 代码示例 function* myGenerator() { yield 1; yield 2; return 3; yield 4; } const iterator = myGenerator(); console.log(iterator.next()); // { value: 1, done: false } console.log(iterator.next()); // { value: 2, done: false } console.log(iterator.next()); // { value: 3, done: true } console.log(iterator.next()); // { value: undefined, done: true }
可以看到,在生成器函数中使用 return
关键字返回了一个值,迭代器在调用 next()
方法时会立即结束并返回该值。
2. 生成器函数可以使用 throw
关键字抛出异常
在 ES6 中,生成器函数无法通过 throw
关键字抛出异常,但是在 ES12 中,生成器函数可以使用 throw
关键字抛出异常,并且可以在函数内部通过 try...catch
捕获异常。
以下是一个使用 throw
关键字的示例:
// javascriptcn.com 代码示例 function* myGenerator() { try { yield 1; yield 2; throw new Error('Oops!'); } catch (error) { console.error(error.message); } } const iterator = myGenerator(); console.log(iterator.next()); // { value: 1, done: false } console.log(iterator.next()); // { value: 2, done: false } console.log(iterator.next()); // Oops! console.log(iterator.next()); // { value: undefined, done: true }
可以看到,在生成器函数中使用 throw
关键字抛出了一个异常,并且在函数内部通过 try...catch
捕获了该异常。
生成器函数的应用
生成器函数可以用于实现异步编程、迭代器、状态机等场景,以下是一个使用生成器函数实现异步编程的示例:
// javascriptcn.com 代码示例 function fetchData(url) { return new Promise(resolve => { setTimeout(() => { resolve(`Data from ${url}`); }, 1000); }); } function* myGenerator() { const data1 = yield fetchData('https://www.example.com/api/1'); console.log(data1); const data2 = yield fetchData('https://www.example.com/api/2'); console.log(data2); const data3 = yield fetchData('https://www.example.com/api/3'); console.log(data3); } function runGenerator(generator) { const iterator = generator(); function iterate(iteration) { if (iteration.done) { return Promise.resolve(iteration.value); } return Promise.resolve(iteration.value) .then(x => iterate(iterator.next(x))) .catch(x => iterate(iterator.throw(x))); } return iterate(iterator.next()); } runGenerator(myGenerator);
可以看到,在 myGenerator
函数中使用了 fetchData
函数获取数据,然后使用 yield
关键字暂停函数的执行并返回数据,最后通过 runGenerator
函数执行生成器函数并返回 Promise 对象,使用 Promise 的链式调用实现了异步编程。
总结
ES12 中增强了生成器函数的功能,可以使用 return
关键字返回值,使用 throw
关键字抛出异常,这些新特性可以让生成器函数在实现异步编程、迭代器、状态机等场景时更加方便和灵活。我们可以通过学习生成器函数的基础知识和用法,掌握 ES12 中的生成迭代器技术,提高前端开发的效率和质量。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65843715d2f5e1655def624c