120

Javascript中有没有一种方法可以轻松编写这样的内容:

[1,2,3].times do {
  something();
}

任何可能支持某些类似语法的库?

更新:澄清 - 我想something()为每个数组元素迭代分别调用 1,2 和 3 次

4

23 回答 23

124

只需使用一个for循环:

var times = 10;

for(var i = 0; i < times; i++){
    doSomething();
}
于 2012-06-12T09:27:46.600 回答
95

可能的 ES6 替代方案。

Array.from(Array(3)).forEach((x, i) => {
  something();
});

而且,如果您希望它“分别被调用 1,2 和 3 次”。

Array.from(Array(3)).forEach((x, i) => {
  Array.from(Array(i+1)).forEach((x, i2) => {
    console.log(`Something ${ i } ${ i2 }`)
  });
});

更新:

取自fill-arrays-with-undefined

这似乎是创建初始数组的一种更优化的方式,我还更新了它以使用@felix-eve 建议的第二个参数映射函数。

Array.from({ length: 3 }, (x, i) => {
  something();
});
于 2016-08-30T15:50:40.327 回答
53

这个答案是基于Array.forEach,没有任何库,只是原生香草

要基本上调用something()3 次,请使用:

[1,2,3].forEach(function(i) {
  something();
});

考虑以下功能:

function something(){ console.log('something') }

输出将是:

something
something
something

要完成这个问题,这里有一种something()分别调用 1、2 和 3 次的方法:

现在是 2017 年,你可以使用 ES6:

[1,2,3].forEach(i => Array(i).fill(i).forEach(_ => {
  something()
}))

或者在旧的 ES5 中:

[1,2,3].forEach(function(i) {
  Array(i).fill(i).forEach(function() {
    something()
  })
}))

在这两种情况下,输出将是

输出将是:

something

something
something

something
something
something

(一次,两次,然后3次)

于 2015-12-03T19:29:00.197 回答
36

在使用之前创建一个数组和fill所有项目:undefinedmap

阅读map跳过从未定义的数组项的详细原因

⚠️Array.fill没有IE支持

Array(5).fill().map((item, i) => console.log(item, i))

或者通过解构 Array进行与上述相同的操作,如果未设置项目的值,则会自动为每个项目设置: undefined

[...Array(5)].map((item, i) => console.log(item, i))


如果您想让上述内容更具“声明性”,我目前基于意见的解决方案将是:

const iterate = times => callback => [...Array(times)].map((n,i) => callback(i))

iterate(3)(console.log)


使用老式(反向)循环:

// run 5 times:
for( let i=5; i--; )
   console.log(i) 

或作为声明性的"while"

const run = (cb, ...args) => count => { while(count--) cb(...args) }

// executes the callback with whatever arguments, 3 times
run(console.log, 1,2,3)(3)

于 2018-07-18T10:31:59.367 回答
23

使用lodash

_.each([1, 2, 3], (item) => {
   doSomeThing(item);
});

//Or:
_.each([1, 2, 3], doSomeThing);

或者如果你想做N 次

const N = 10;
_.times(N, () => {
   doSomeThing();
});

//Or shorter:
_.times(N, doSomeThing);

安装参考这个链接lodash

于 2016-08-20T04:25:10.870 回答
19

既然你提到了下划线:

假设f是您要调用的函数:

_.each([1,2,3], function (n) { _.times(n, f) });

会成功的。例如,使用f = function (x) { console.log(x); },您将进入控制台: 0 0 1 0 1 2

于 2012-06-12T10:05:41.047 回答
17

您也可以对解构执行相同的操作,如下所示

[...Array(3)].forEach( _ => console.log('do something'));

或者如果你需要索引

[...Array(3)].forEach(( _, index) => console.log('do something'));
于 2019-10-08T11:14:23.257 回答
10

如果不能使用 Underscorejs,可以自己实现。通过将新方法附加到 Number 和 String 原型,您可以这样做(使用 ES6 箭头函数):

// With String
"5".times( (i) => console.log("number "+i) );

// With number variable
var five = 5;
five.times( (i) => console.log("number "+i) );

// With number literal (parentheses required)
(5).times( (i) => console.log("number "+i) );

您只需创建一个函数表达式(任何名称)并将其分配给您想要访问它的任何属性名称(在原型上):

var timesFunction = function(callback) {
  if (typeof callback !== "function" ) {
    throw new TypeError("Callback is not a function");
  } else if( isNaN(parseInt(Number(this.valueOf()))) ) {
    throw new TypeError("Object is not a valid number");
  }
  for (var i = 0; i < Number(this.valueOf()); i++) {
    callback(i);
  }
};

String.prototype.times = timesFunction;
Number.prototype.times = timesFunction;
于 2015-10-24T08:51:11.323 回答
2

有一个很棒的库叫做 Ramda,它类似于 Underscore 和 Lodash,但更强大。

const R = require('ramda');

R.call(R.times(() => {
    console.log('do something')
}), 5);

Ramda 包含很多有用的功能。参见Ramda 文档

于 2019-01-07T08:57:28.420 回答
1

只需使用嵌套循环(可能包含在函数中)

function times( fct, times ) {
  for( var i=0; i<times.length; ++i ) {
    for( var j=0; j<times[i]; ++j ) {
      fct();
    }
  }
}

然后像这样调用它:

times( doSomething, [1,2,3] );
于 2012-06-12T09:31:46.300 回答
1
times = function () {
    var length = arguments.length;
    for (var i = 0; i < length ; i++) {
        for (var j = 0; j < arguments[i]; j++) {
            dosomthing();
        }
    }
}

你可以这样称呼它:

times(3,4);
times(1,2,3,4);
times(1,3,5,7,9);
于 2012-06-12T10:08:20.640 回答
1
var times = [1,2,3];

for(var i = 0; i < times.length;  i++) {
  for(var j = 0; j < times[i];j++) {
     // do something
  }
}

使用 jQuery.each()

$([1,2,3]).each(function(i, val) {
  for(var j = 0; j < val;j++) {
     // do something
  }
});

或者

var x = [1,2,3];

$(x).each(function(i, val) {
  for(var j = 0; j < val;j++) {
     // do something
  }
});

编辑

您可以使用纯 JS 执行以下操作:

var times = [1,2,3];
times.forEach(function(i) {
   // do something
});
于 2012-06-12T09:28:42.047 回答
1

您可以使用

Array.forEach

例子:

function logArrayElements(element, index, array) {  
    console.log("a[" + index + "] = " + element);  
}  
[2, 5, 9].forEach(logArrayElements)

或使用 jQuery

$.each([52, 97], function(index, value) { 
  alert(index + ': ' + value); 
});

http://api.jquery.com/jQuery.each/

于 2012-06-12T09:34:06.500 回答
1

简单的一会儿怎么样。

let times = 5;

while (times--) {

    console.log(times+1)

}

关于其工作原理的参考:FalsyDecrement (--)

于 2022-01-20T16:56:15.043 回答
1

Array.from (ES6)

function doSomthing() {
    ...
}

像这样使用它:

Array.from(Array(length).keys()).forEach(doSomthing);

或者

Array.from({ length }, (v, i) => i).forEach(doSomthing);

或者

// array start counting from 1
Array.from({ length }, (v, i) => ++i).forEach(doSomthing);
于 2018-08-29T15:08:57.300 回答
1
// calls doSomething 42 times
Array( 42 ).join( "x" ).split( "" ).forEach( doSomething );

// creates 42 somethings
var somethings = Array( 42 ).join( "x" ).split( "" ).map( () => buildSomething(); );

或(通过https://stackoverflow.com/a/20066663/275501

Array.apply(null, {length: 42}).forEach( doSomething );
于 2016-03-30T18:00:59.583 回答
1
const loop (fn, times) => {
  if (!times) { return }
  fn()
  loop(fn, times - 1)
}

loop(something, 3)
于 2017-06-06T20:47:39.180 回答
0

假设我们可以使用一些像扩展运算符这样的 ES6 语法,我们会想要做的次数与集合中所有数字的总和一样多。

在这种情况下,如果 times 等于[1,2,3],则总次数将为 6,即 1+2+3。

/**
 * @param {number[]} times
 * @param {cb} function
 */
function doTimes(times, cb) {
  // Get the sum of all the times
  const totalTimes = times.reduce((acc, time) => acc + time);
  // Call the callback as many times as the sum
  [...Array(totalTimes)].map(cb);
}

doTimes([1,2,3], () => console.log('something'));
// => Prints 'something' 6 times

如果构造和传播数组背后的逻辑不明显,这篇文章应该会有所帮助。

于 2019-01-28T03:00:10.683 回答
0

给定一个函数something

function something() { console.log("did something") }

并在原型times中添加了一个新方法:Array

Array.prototype.times = function(f){
  for(v of this) 
    for(var _ of Array(v))
      f();
}

这段代码:

[1,2,3].times(something)

输出这个:

did something
did something
did something
did something
did something
did something

认为这回答了您更新的问题(5 年后),但我想知道在阵列上进行这项工作有多大用处?效果会不会和 call 一样[6].times(something),而 call 又可以写成:

for(_ of Array(6)) something();

(虽然_如果你使用它作为垃圾变量可能会破坏lodash或下划线)

于 2017-07-03T03:07:32.173 回答
0

打字稿实现:

对于那些对如何实现String.times以及Number.times以一种类型安全且与thisArg.

declare global {
    interface Number {
        times: (callbackFn: (iteration: number) => void, thisArg?: any) => void;
    }
    interface String {
        times: (callbackFn: (iteration: number) => void, thisArg?: any) => void;
    }
}

Number.prototype.times = function (callbackFn, thisArg) {
    const num = this.valueOf()
    if (typeof callbackFn !== "function" ) {
        throw new TypeError("callbackFn is not a function")
    }
    if (num < 0) {
        throw new RangeError('Must not be negative')
    }
    if (!isFinite(num)) {
        throw new RangeError('Must be Finite')
    }
    if (isNaN(num)) {
        throw new RangeError('Must not be NaN')
    }

    [...Array(num)].forEach((_, i) => callbackFn.bind(thisArg, i + 1)())
    // Other elegant solutions
    // new Array<null>(num).fill(null).forEach(() => {})
    // Array.from({length: num}).forEach(() => {})
}

String.prototype.times = function (callbackFn, thisArg) {
    let num = parseInt(this.valueOf())
    if (typeof callbackFn !== "function" ) {
        throw new TypeError("callbackFn is not a function")
    }
    if (num < 0) {
        throw new RangeError('Must not be negative')
    }
    if (!isFinite(num)) {
        throw new RangeError('Must be Finite')
    }
    // num is NaN if `this` is an empty string 
    if (isNaN(num)) {
        num = 0
    }

    [...Array(num)].forEach((_, i) => callbackFn.bind(thisArg, i + 1)())
    // Other elegant solutions
    // new Array<null>(num).fill(null).forEach(() => {})
    // Array.from({length: num}).forEach(() => {})
}

可以在此处找到带有一些示例的TypeScript Playground链接

这篇文章实现了由Andreas Bergström、 vinyl 、Ozay DumanSeregPie发布的解决方案

于 2020-06-07T03:48:22.270 回答
0

这些答案都很好,IMO @Andreas 是最好的,但很多时候在 JS 中我们必须异步执行操作,在这种情况下,async 已经涵盖了:

http://caolan.github.io/async/docs.html#times

const async = require('async');

async.times(5, function(n, next) {
    createUser(n, function(err, user) {
        next(err, user);
    });
}, function(err, users) {
    // we should now have 5 users
});

这些“时间”功能对于大多数应用程序代码来说不是很有用,但对测试应该很有用。

于 2017-01-18T20:15:34.920 回答
0

使用Array.from.forEach

let length = 5;
Array.from({length}).forEach((v, i) => {
  console.log(`#${i}`);
});

于 2018-11-15T16:07:36.003 回答
0

只是想我要补充一下,有一个漂亮的 JS 方法被调用.repeat(n),它会重复一个字符串“n”次。因此,如果您正在寻找可以重复字符串“n”次的内容...

function repeatString (number, string) {
  return string.repeat(number);
}

所以如果你这样做...

repeatString(3, 'Hey there! ');

你会得到:'嘿!嘿!嘿!'

于 2021-05-31T15:19:11.873 回答