如何在JavaScript中创建一个可迭代对象?



我试图通过创建一个范围函数来理解JavaScript中的可迭代对象,但它不起作用

我试图理解JavaScript中的可迭代对象,所以我创建了一个range函数,当我调用它时,它会为我返回一个数字范围,例如:

for (let i of Range(5)) console.log(i);
0
1
2
3
4

下面是执行此操作的代码。

// log function
const log = console.log;
// Range constructor 
function Range(end, start, step = 1) {
if (!new.target) {
return new Range(start, end, step);
}
end = start ? start : end;
start = start ? end : 0;
step = step;

return {
start,
end,
step,
[Symbol.iterator]() {
return this;
},
next() {
if (this.start < this.end) {
this.start += this.step;
return {
done: false,
value: this.start - this.step
};
} else {
return { done: true };
}
}
}
}

但是当我运行它时,返回一个接一个的数字,例如

let range = new Range(6);
for (i of range) log(i);

输出
0
1
2
3
4
5

但是当我像for (let i of Range(5) log(i);一样运行它时,它返回undefined为什么!

如果通过将return new Range(start, end, step);更新为return new Range(end, start, step);end = start ? start : end;更新为end = start ?? end;来解决问题

所以当我运行

let range = new Range(5); 
for (let i of range) log( i ); // 0, 1, 2, 3, 4
for (let i of Range(10) ) log( i ); // 0, 1, 2, 3, 4

但是出现了一个新的问题

let arr = Array.from(range); 
log(arr) // []

如何修复

您在new Range(start, end, step)中混淆了您的论点(感谢@Unmitigated)。应该是new Range(end, start, step)


仅供参考,生成器函数要简单得多。

function* range(start, end, step = 1) {
if (end === undefined) {
end = start;
start = 0;
}
for (; start < end; start += step) {
yield start;
}
}

这样怎么样?

let range = {
from: 1,
to: 5
};
// 1. call to for..of initially calls this. 
range[Symbol.iterator] = function() {
return {
current: this.from,
last: this.to,
// 3. next() is called on each iteration by the for..of loop
next() {
if (this.current <= this.last) {
return {
done: false,
value: this.current++
};
} else {
return {
done: true
};
}
}
};
};
for (let num of range) {
console.log(num); // 1, then 2, 3, 4, 5
}

如果我们需要考虑stepSize,我们可以定义如下函数:

function myInterator(start = 0, end = 5, 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;
}

现在,按如下方式使用函数:

const it = myIterator(1, 5, 1);
let result = it.next();
while (!result.done) {
console.log(result.value); // 1 2 3 4 5
result = it.next();
}

最新更新