使用javascript中的数组,可以很容易地获得用于迭代的当前索引。您可以使用forEach
并且索引是第二个条目,或者使用for...of
和.entries()
以及数组解压缩。
但是生成器没有.entries()
方法。如何在for...of
循环中获取生成器的当前索引?
我基本上想要
function* myGen(){
let i = 0;
while(true) {
i+=1;
yield i;
}
}
for(let [j, index] of myGen().entries()) { //<-- I want .entries() but for a Generator
//...
}
//Running the above produces TypeError: myGen(...).entries(...) is not a function or its return value is not iterable
答案 0 :(得分:3)
不建议将内容添加到内置原型中,但是如果您确实希望代码像那样工作(在任何生成器上调用.entries()
),则可以按照以下步骤操作:
const Generator = Object.getPrototypeOf(function* () {});
Generator.prototype.entries = function * () {
let i = 0;
for (let value of this) {
yield [i++, value];
}
}
// Demo
function* myGen(){
let i = 64;
while(i < 70) {
i+=1;
yield String.fromCharCode(i);
}
}
for(let [j, index] of myGen().entries()) { //<-- Now you have .entries() on a Generator
console.log(j, index);
}
但是,定义实用程序功能更为谨慎。
const GeneratorUtils = {
* entriesOf(iter) {
let i = 0;
for (let value of iter) {
yield [i++, value];
}
}
};
// Demo
function* myGen(){
let i = 64;
while(i < 70) {
i+=1;
yield String.fromCharCode(i);
}
}
for(let [j, index] of GeneratorUtils.entriesOf(myGen())) {
console.log(j, index);
}
答案 1 :(得分:1)
但是生成器没有
.entries()
方法。我如何获得最新的 我的for...of
循环中生成器的索引?
您可以在数组文字和.entries()
的{{1}}方法内利用扩展元素在生成器函数之前调用
Array.prototype
答案 2 :(得分:0)
没有内置的方法可以执行-生成器将必须
function* myGen(){
let index = 0;
while(index < 10) {
const item = 'foo' + index;
yield { item, index };
index++;
}
}
for(const { item, index } of myGen()) {
console.log('item: ' + item);
console.log('index: ' + index);
}
如果您无法修改想要获取索引的生成器,则可以将其放置在另一个生成器中,该生成器 会跟踪索引(或者您也可以在每次外部迭代时递增):
function* unmodifiableGen(){
// index is private, is not being yielded
let index = 0;
while(index < 10) {
yield Math.random();
index++;
}
}
function* generatorCounter(gen) {
// this index *will* be yielded:
let index = 0;
for (const item of gen()) {
yield { item, index };
index++;
}
}
for(const { item, index } of generatorCounter(unmodifiableGen)) {
console.log('item: ' + item);
console.log('index: ' + index);
}
答案 3 :(得分:0)
一种稍微不同的方法可能是使myGen()
成为一个常规函数,该函数返回遵守迭代器协议而不是生成器的对象。然后,您可以给它一个entries()
方法。它的工作方式与生成器有所不同(您不能直接在其上调用next()
)。但是它是独立的,在预期迭代器的情况下应该可以按预期工作:
function myGen(start, stop){
return {
[Symbol.iterator]: function* () {
while(start < stop){
yield start++
}
},
entries: function* entries (){
let i = 0
for (n of this){
yield [i++, n]
}
}
}
}
let g = myGen(10, 20)
// works like a regular iterator:
console.log([...g])
// but you can also call entries():
g = myGen(2, 9)
for ([i, n] of g.entries()){
console.log(`index: ${i}, value: ${n}`)
}