#javascript #iterator #iterable #ecmascript-next
#javascript #итератор #итерируемый #ecmascript-следующий
Вопрос:
согласно спецификации ECMAScript объект, реализующий интерфейс итератора, должен иметь next
метод, но есть также необязательные методы return
и throw
(смотрите Спецификации здесь:https://tc39.es/ecma262/#sec-iteration)
приводя пример кода во фрагменте, почему throw
метод никогда не вызывается в цикле for-of, но вместо него вызывается return
метод?
class Iterable {
constructor(name) {
this.name = name;
}
[Symbol.iterator]() {
let done = false;
function implementation() {
if (done) {
return {
done: true,
value: undefined,
};
}
done = true;
return {
done: false,
value: undefined,
};
}
return {
next: (...args) => {
console.log(
`${this.name}: next called, done=${JSON.stringify(
done
)}, args=${JSON.stringify(args)}`
);
return implementation();
},
return: (...args) => {
console.log(
`${this.name}: return called, done=${JSON.stringify(
done
)}, args=${JSON.stringify(args)}`
);
return implementation();
},
throw: (...args) => {
console.log(
`${this.name}: throw called, done=${JSON.stringify(
done
)}, args=${JSON.stringify(args)}`
);
return implementation();
},
};
}
}
(() => {
for (const item of new Iterable("standard")) {
// pass
}
})();
(() => {
for (const item of new Iterable("return")) {
return "test";
}
})();
(() => {
for (const item of new Iterable("break")) {
break;
}
})();
(() => {
for (const item of new Iterable("continue")) {
continue;
}
})();
(() => {
try {
for (const item of new Iterable("throw")) {
throw new Error(`${item}`);
}
} catch {
// pass
}
})();
вывод на консоль:
standard: next called, done=false, args=[]
standard: next called, done=true, args=[]
return: next called, done=false, args=[]
return: return called, done=true, args=[]
break: next called, done=false, args=[]
break: return called, done=true, args=[]
continue: next called, done=false, args=[]
continue: next called, done=true, args=[]
throw: next called, done=false, args=[]
throw: return called, done=true, args=[]
Комментарии:
1. Почему должен быть вызван
throw
метод? Это было бы катастрофой, потому что это делает код непредсказуемым.throw
используется для информирования генератора об ошибке.2. @abetteroliver имеет смысл, не могли бы вы привести мне пример, как это используется? или что скрывается за вашим последним предложением — я имею в виду, предназначено ли оно для использования при ручном использовании генератора?