脚本宝典收集整理的这篇文章主要介绍了迭代器和生成器,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
参考高级程序设计4
for循环是一种最简单的迭代,循环是迭代机制的基础,循环可以指定迭代的次数,迭代在一个有序集合上进行,如数组。
数组有已知长度且可以通过索引获取,所以在循环的时候可以通过递增的方式来遍历,因为以下几个原因循环来执行例程并不理想。
es5新增高阶函数forEach就是为了解决这个问题而诞生的,但是它不能识别何时终止迭代
迭代器模式和可迭代协议
let str = 'abc'
let arr = ['a', 'b', 'c']
console.log(str[Symbol.iterator])
console.log(arr[Symbol.iterator])
// f values() { [native code] }
// f values() { [native code] }
迭代器协议 可以通过next()调用迭代器,返回一个 IteratorResult 对象。IteratorResult中有done和value两个属性,done返回布尔值来确定后面是否还有值,done为true时表示状态耗尽,不能再次迭代。value返回对应的当前值
const arr = [1, 2]
const iter = arr[Symbol.iterator]()
console.log(iter.next()); // { done: false, value: 1 }
console.log(iter.next()); // { done: false, value: 2 }
console.log(iter.next()); // { done: true, value: undefined }
每个迭代器都表示对可迭代对象的一次性有序遍历。不同迭代器的实例相互之间没有联系,只会独 立地遍历可迭代对象
const arr = [1, 2]
const iter = arr[Symbol.iterator]()
const iter2 = arr[Symbol.iterator]()
console.log(iter.next()); // { done: false, value: 1 }
console.log(iter.next()); // { done: false, value: 2 }
console.log(iter2.next()); // { done: false, value: 1 }
console.log(iter2.next()); // { done: false, value: 2 }
自定义迭代器
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 };
}
},
return () {
return { done: true };
}
};
}
}
const counter = new Counter(3)
for (const item of counter) {
if (item > 2) {
continue
}
console.log(item) // 1, 2
}
// return和yield同样的效果,但是yield能写多个, 如果有多个return那么后面的代码都不会执行,只会执行第一个return
function* generatorFn(opt) {
yield opt;
yield '1';
return '2';
return '3';
}
//
const fn = generatorFn('123')
console.log(fn.next(), fn.next(), fn.next(), fn.next())
// {value: '123', done: false}
// {value: '1', done: false}
// {value: '2', done: true}
// {value: undefined, done: true}
console.log(bbb.next())
// {value: '123', done: false}
生成器作为可迭代对象
function* nTimes(n) {
while(n--) {
yield n;
}
}
for (const i of nTimes(3)) {
console.log(i) // 直接得到value, 返回的不是{ done,value }
}
function* generatorFn (opt) {
console.log(yield) // 作为函数中间参数使用
console.log(yield)
console.log(yield)
}
// 如果 yield 在第一行 后面没有东西返回0,其他的yield后面没有东西返回undefined
const generfn = generatorFn()
generfn.next() // 0
generfn.next() // undefined
generfn.next() // undefined
function* generator (opt) {
console.log(opt)
console.log(yield)
console.log(yield)
}
const gener = generator(123)
gener.next(321) // 123, 因为正在调用生成器
gener.next(456) // 456
gener.next(789) // 789
yield 关键字可以同时用于输入和输出
const gener = generator()
console.log(gener.next(), gener.next(456))
// {value: '123', done: false}
// {value: 456, done: true}
// 函数要对表达式求值才能确定返回的值,当遇到yield时并计算值123,
// 下一次调用的时候传入了456,交给同一个yield处理,
// 然后456被确定为生成器函数产出的值
通过“ * ”加强yield
function* generatorFn2 () {
yield* [1, 2, 3]
// 等价于
// for (const i of [1, 2, 3]) {
// yield i
// }
}
console.log(Array.from(generatorFn2())) // [1, 2, 3]
通过yield*调用生成器
function* innerFn() {
yield 'foo';
return 'bar';
}
function* outerFn(genObj) {
console.log('iter value:', yield* innerFn());
}
for (const x of outerFn()) {
console.log('value:', x);
}
生成器作为默认迭代器
// 生成器函数 产生一个生成器函数
class Foo {
constructor (opt) {
this.opt = opt
}
* [Symbol.iterator] () {
yield* this.opt
}
}
for (const key of new Foo([1, 2, 3])) {
console.log(key)
}
终止生成器 使用throw(), return() 终止生成器
// 所有的生成器都有 return() 会提前进入结束状态, 后续调用都是 done: true
function * Fn () {
for (const item of [1, 2, 3]) {
yield item
}
}
const fn = Fn()
console.log(fn.next()) // {value: 1, done: false}
console.log(fn.return(666)) // {value: 666, done: true} value默认undefined
function* Fn2() {
for (const x of [1, 2, 3]) {
yield x
}
}
const g = Fn2()
for (const x of g) {
if (x > 1) {
g.return(4);
}
console.log(x); // 1, 2
}
// 通过throw 来调用会抛出一个错误,如果处理这个错误会继续往下面执行
function* Fn2() {
yield* [1, 2, 3]
}
const fn2 = Fn2()
try {
fn2.throw('困')
} catch (err) {
console.log(err) // 困
}
// 如果在生成器内部处理这个错误,那么调用throw时会跳过对应的这一项,如果throw放在所有next前面,也不会执行后面的
function* Fn3() {
for (const item of [1, 2, 3]) {
try {
yield item
} catch {}
}
}
const fn3 = Fn3()
console.log(fn3.next()) // 1
fn3.throw('困') // yield抛出一个错误,不会在产出2
console.log(fn3.next()) // 3
以上是脚本宝典为你收集整理的迭代器和生成器全部内容,希望文章能够帮你解决迭代器和生成器所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。