JavaScript Iterators & Generators (yield, next, custom iterators) Quiz
Answer 35 questions covering iterator protocol basics, next() behavior, iterable objects, generator syntax, yield mechanics, execution control, passing values, custom iterators, lazy generator use cases, and async-iterator differences.
Question 1
What does the iterator protocol require from an object returned by Symbol.iterator?
Question 2
What prints?
const iterable = {
values: ['a', 'b'],
[Symbol.iterator]() {
let index = 0
return {
next: () => (index < this.values.length
? { value: this.values[index++], done: false }
: { value: undefined, done: true })
}
}
}
const iterator = iterable[Symbol.iterator]()
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
Question 3
What is the difference between an iterable and an iterator?
Question 4
What prints?
const iterator = [10, 20][Symbol.iterator]()
console.log(iterator.next().value)
console.log(iterator.next().done)
console.log(iterator.next().done)
Question 5
Why is returning { done: true } required when iteration finishes?
Question 6
How does for...of work with iterables?
Question 7
What prints?
const iterator = {
current: 1,
next() {
if (this.current <= 3) {
return { value: this.current++, done: false }
}
return { value: undefined, done: true }
}
}
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
Question 8
Why can iterators be stateful without being iterable?
Question 9
What prints?
function* numbers() {
yield 1
yield 2
}
const iterator = numbers()
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
Question 10
Why do generator functions use function* syntax?
Question 11
How does yield pause execution?
Question 12
What prints?
function* steps() {
yield 'load'
return 'done'
}
const iterator = steps()
console.log(iterator.next())
console.log(iterator.next())
Question 13
Why should you usually ignore the final value returned from a generator?
Question 14
What happens if you call next() after done becomes true?
Question 15
What prints?
function* echo() {
const first = yield 'ready'
return `received ${first}`
}
const iterator = echo()
console.log(iterator.next())
console.log(iterator.next('data'))
Question 16
How does passing a value to iterator.next(value) affect the generator?
Question 17
What does iterator.throw(error) do on a generator?
Question 18
What prints?
function* reader() {
try {
yield 'waiting'
} catch (error) {
return `handled ${error.message}`
}
}
const iterator = reader()
console.log(iterator.next())
console.log(iterator.throw(new Error('oops')))
Question 19
What does the yield* keyword do?
Question 20
What prints?
function* letters() {
yield* ['x', 'y']
yield 'z'
}
const iterator = letters()
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
Question 21
Why are generators ideal for lazy sequences?
Question 22
How does lazy evaluation benefit performance?
Question 23
What prints?
const iterableRange = (start, end) => ({
[Symbol.iterator]() {
let current = start
return {
next() {
if (current <= end) {
return { value: current++, done: false }
}
return { value: undefined, done: true }
}
}
}
})
console.log([...iterableRange(3, 5)])
Question 24
What role does Symbol.iterator play in custom data structures?
Question 25
What prints?
function* idMaker() {
let id = 0
while (true) {
yield id++
}
}
const iterator = idMaker()
console.log(iterator.next().value)
console.log(iterator.next().value)
console.log(iterator.next().value)
Question 26
Why can generators simplify complex control flows?
Question 27
How do generators differ from async generators?
Question 28
How does for await...of interact with async generators?
Question 29
What benefit do async generators provide over pulling from an async function repeatedly?
Question 30
Why are generators handy for implementing lazy pipelines such as map/filter chains?
Question 31
What prints?
const oddIterator = {
value: 1,
next() {
const result = { value: this.value, done: false }
this.value += 2
if (this.value > 5) return { value: result.value, done: true }
return result
}
}
console.log(oddIterator.next())
console.log(oddIterator.next())
console.log(oddIterator.next())
Question 32
How can you expose the generator’s final return value to callers?
Question 33
Why should custom iterators be careful when caching iterator state on the iterable itself?
Question 34
How can generators coordinate asynchronous actions when paired with a runner?
Question 35
What is a common mistake when consuming iterators manually?
