我试图通过创建一个范围函数来理解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();
}