在JavaScript中循环x次的典型方法是:
for (var i = 0; i < x; i++)
doStuff(i);
但我不想使用++运算符或任何可变变量。那么在ES6中,是否有一种方法来循环x乘以另一种方法?我喜欢Ruby的机制:
x.times do |i|
do_stuff(i)
end
JavaScript/ES6中有类似的吗?我可以欺骗自己的生成器:
function* times(x) {
for (var i = 0; i < x; i++)
yield i;
}
for (var i of times(5)) {
console.log(i);
}
当然,我仍然在使用i++。至少它在视线之外:),但我希望在ES6中有更好的机制。
使用ES2015 Spread操作符:
[...阵列(n)](文件夹)。
const res = [...Array(10)].map((_, i) => {
return i * 10;
});
// as a one liner
const res = [...Array(10)].map((_, i) => i * 10);
或者如果你不需要结果:
[...Array(10)].forEach((_, i) => {
console.log(i);
});
// as a one liner
[...Array(10)].forEach((_, i) => console.log(i));
或者使用ES2015 Array.from操作符:
Array.from(…)
const res = Array.from(Array(10)).map((_, i) => {
return i * 10;
});
// as a one liner
const res = Array.from(Array(10)).map((_, i) => i * 10);
注意,如果你只是需要重复一个字符串,你可以使用string .prototype.repeat。
console.log("0".repeat(10))
// 0000000000
我认为最好的解决方案是使用let:
for (let i=0; i<100; i++) …
这将为每个主体求值创建一个新的(可变的)i变量,并确保i只在循环语法中的增量表达式中更改,而不是从其他任何地方更改。
我可以作弊,自己做一个发电机。至少i++是看不到的:)
在我看来,这应该足够了。即使在纯语言中,所有的操作(或者至少它们的解释器)都是由使用突变的原语构建的。只要它的作用域是正确的,我看不出这有什么错。
你应该可以接受
function* times(n) {
for (let i = 0; i < n; i++)
yield i;
}
for (const i of times(5)) {
console.log(i);
}
但我不想使用++运算符或任何可变变量。
那么你唯一的选择就是使用递归。你也可以在没有可变i的情况下定义生成器函数:
function* range(i, n) {
if (i >= n) return;
yield i;
return yield* range(i+1, n);
}
times = (n) => range(0, n);
但对我来说,这似乎有点过头了,可能会有性能问题(因为尾调用消除无法用于返回收益*)。
Array(100).fill().map((_,i)=> console.log(i) );
这个版本满足了OP对不变性的要求。还要根据您的用例考虑使用reduce而不是map。
这也是一个选择,如果你不介意在你的原型中做一点改变的话。
Number.prototype.times = function(f) {
return Array(this.valueOf()).fill().map((_,i)=>f(i));
};
现在我们可以这么做了
((3).times(i=>console.log(i)));
+1到arcseldon的.fill建议。
我用一个helper函数包装了@Tieme的答案。
在打字稿:
export const mapN = <T = any[]>(count: number, fn: (...args: any[]) => T): T[] => [...Array(count)].map((_, i) => fn())
现在你可以运行:
const arr: string[] = mapN(3, () => 'something')
// returns ['something', 'something', 'something']
此解决方案的优点
最容易阅读/使用(我觉得)
返回值可以用作和,也可以忽略
普通es6版本,也链接到TypeScript版本的代码
缺点
——突变。只是内在我不在乎,也许其他人也不在乎。
示例和代码
times(5, 3) // 15 (3+3+3+3+3)
times(5, (i) => Math.pow(2,i) ) // 31 (1+2+4+8+16)
times(5, '<br/>') // <br/><br/><br/><br/><br/>
times(3, (i, count) => { // name[0], name[1], name[2]
let n = 'name[' + i + ']'
if (i < count-1)
n += ', '
return n
})
function times(count, callbackOrScalar) {
let type = typeof callbackOrScalar
let sum
if (type === 'number') sum = 0
else if (type === 'string') sum = ''
for (let j = 0; j < count; j++) {
if (type === 'function') {
const callback = callbackOrScalar
const result = callback(j, count)
if (typeof result === 'number' || typeof result === 'string')
sum = sum === undefined ? result : sum + result
}
else if (type === 'number' || type === 'string') {
const scalar = callbackOrScalar
sum = sum === undefined ? scalar : sum + scalar
}
}
return sum
}
TypeScipt版本
https://codepen.io/whitneyland/pen/aVjaaE?editors=0011