前端面试题库

迭代器和生成器

迭代器生成器更新时间:2024-08-26 09:28:27

答案

迭代器

在 JavaScript 中,迭代器是一个对象,它定义一个序列,并在终止时附带一个返回值。迭代器实际就是通过next()方法实现了迭代器协议的任何一个对象,该方法返回两个属性:

  • value: 返回的值;
  • done: 如果迭代到最后一个值,返回true,否则返回false

一旦创建,迭代器就可以重复调用next(),在迭代到最后一个值后,继续调用就会返回{done: true}

下面的函数返回一个范围迭代器,返回从startend的值,包含start,不包含end

function makeRangeIterator(start = 0, end = Infinity, step = 1) { let nextIndex = start; let iterationCount = 0; const rangeIterator = { next() { let result; if (nextIndex < end) { result = { value: nextIndex, done: false }; nextIndex += step; iterationCount++; return result; } return { value: iterationCount, done: true }; }, }; return rangeIterator; }

使用方式如下:

let it = makeRangeIterator(1, 10, 2); let result = it.next(); while (!result.done) { console.log(result.value); // 1 3 5 7 9 result = it.next(); } console.log(`已迭代序列的大小:${result.value}`); // 5
生成器函数

由于自定义迭代器需要自己管理状态,JavaScript提供了生成器(Generator):它允许你定义一个非连续的函数作为迭代算法。

使用function*语法,初次调用时不执行函数,而是返回一个生成器,通过调用next()消耗该生成器,生成器函数将执行,直到遇到yield关键字。

可以多次调用该函数,每次都会返回新的生成器,但每个生成器只能迭代一次。

function* makeRangeIterator(start = 0, end = Infinity, step = 1) { let iterationCount = 0; for (let i = start; i < end; i += step) { iterationCount++; yield i; } return iterationCount; } const gen = makeRangeIterator(1, 10, 2); // 初次调用返回一个gen生成器 console.log(gen.next()); // {value: 1, done: false} console.log(gen.next()); // {value: 3, done: false} console.log(gen.next()); // {value: 5, done: false} console.log(gen.next()); // {value: 7, done: false} console.log(gen.next()); // {value: 9, done: false} console.log(gen.next()); // {value: 5, done: true} // 最后一次done=true console.log(gen.next()); // {value: undefined, done: true} // 继续调用值就为undefined了
可迭代对象

如果一个对象可以通过for...of进行循环,那么该对象是一个可迭代对象。一些内置对象比如ArrayTypedArrayMapSetString默认拥有迭代行为,而其他Object没有。

为了让对象可迭代,可以实现[Symbol.iterator]()方法,就是对像的Symbol.iterator属性,可迭代对象可以多次迭代。

var myIterable = { *[Symbol.iterator]() { yield 1; yield 2; yield 3; }, }; for (let value of myIterable) { console.log(value); } // 1 // 2 // 3 [...myIterable] // [1, 2, 3]

评论