I am learning the JavaScript ES6 iterator pattern and came across this problem:
const counter = [1, 2, 3, 4, 5];
const iter = counter[Symbol.iterator]();
iter.return = function() {
console.log("exiting early");
return { done: true };
};
for (let i of iter) {
console.log(i);
if (i >= 3) {
break;
}
}
console.log('---');
for (let i of iter) {
console.log(i);
}
// 1
// 2
// 3
// exiting early
// ---
// 4
// 5
So I added a return method definition to the iterator that I extracted from an array. Although the return method got called, it didn't actually close the iterator. By contrast, if I define the iterator return method in definition, it will work as expected:
class Counter {
[Symbol.iterator]() {
let count = 1;
return {
next() {
if (count <= 5) {
return {
done: false,
value: count++
}
} else {
return {
done: true,
value: undefined
}
}
},
return() {
console.log('exiting early');
return { done: true, value: undefined };
}
}
}
}
const myCounter = new Counter();
iter = myCounter[Symbol.iterator]();
for (let i of myCounter) {
console.log(i);
if (i >= 3) {
break;
}
}
console.log('---');
for (let i of myCounter) {
console.log(i);
}
// 1
// 2
// 3
// exiting early
// ---
// 1
// 2
// 3
// 4
// 5
My question is, why did I get this unexpected behavior? I assume that if the return method didn't get called, then the iterator will not close until it reaches the very end by calling next. But adding return property will properly "call" the return method since I got the console log, but doesn't actually terminate the iterator even if I returned { done: true } in the return method.