Javascript中有没有一种方法可以轻松编写这样的内容:
[1,2,3].times do {
something();
}
任何可能支持某些类似语法的库?
更新:澄清 - 我想something()
为每个数组元素迭代分别调用 1,2 和 3 次
Javascript中有没有一种方法可以轻松编写这样的内容:
[1,2,3].times do {
something();
}
任何可能支持某些类似语法的库?
更新:澄清 - 我想something()
为每个数组元素迭代分别调用 1,2 和 3 次
只需使用一个for
循环:
var times = 10;
for(var i = 0; i < times; i++){
doSomething();
}
可能的 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 }`)
});
});
这似乎是创建初始数组的一种更优化的方式,我还更新了它以使用@felix-eve 建议的第二个参数映射函数。
Array.from({ length: 3 }, (x, i) => {
something();
});
这个答案是基于Array.forEach
,没有任何库,只是原生香草。
要基本上调用something()
3 次,请使用:
[1,2,3].forEach(function(i) {
something();
});
考虑以下功能:
function something(){ console.log('something') }
输出将是:
something
something
something
要完成这个问题,这里有一种something()
分别调用 1、2 和 3 次的方法:
[1,2,3].forEach(i => Array(i).fill(i).forEach(_ => {
something()
}))
[1,2,3].forEach(function(i) {
Array(i).fill(i).forEach(function() {
something()
})
}))
在这两种情况下,输出将是
输出将是:
something
something
something
something
something
something
(一次,两次,然后3次)
fill
所有项目:undefined
map
阅读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)
既然你提到了下划线:
假设f
是您要调用的函数:
_.each([1,2,3], function (n) { _.times(n, f) });
会成功的。例如,使用f = function (x) { console.log(x); }
,您将进入控制台:
0 0 1 0 1 2
您也可以对解构执行相同的操作,如下所示
[...Array(3)].forEach( _ => console.log('do something'));
或者如果你需要索引
[...Array(3)].forEach(( _, index) => console.log('do something'));
如果不能使用 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;
有一个很棒的库叫做 Ramda,它类似于 Underscore 和 Lodash,但更强大。
const R = require('ramda');
R.call(R.times(() => {
console.log('do something')
}), 5);
Ramda 包含很多有用的功能。参见Ramda 文档
只需使用嵌套循环(可能包含在函数中)
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] );
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);
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
});
您可以使用
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);
});
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);
// 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 );
const loop (fn, times) => {
if (!times) { return }
fn()
loop(fn, times - 1)
}
loop(something, 3)
假设我们可以使用一些像扩展运算符这样的 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
如果构造和传播数组背后的逻辑不明显,这篇文章应该会有所帮助。
给定一个函数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或下划线)
打字稿实现:
对于那些对如何实现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 Duman和SeregPie发布的解决方案
这些答案都很好,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
});
这些“时间”功能对于大多数应用程序代码来说不是很有用,但对测试应该很有用。
使用Array.from
和.forEach
。
let length = 5;
Array.from({length}).forEach((v, i) => {
console.log(`#${i}`);
});
只是想我要补充一下,有一个漂亮的 JS 方法被调用.repeat(n)
,它会重复一个字符串“n”次。因此,如果您正在寻找可以重复字符串“n”次的内容...
function repeatString (number, string) {
return string.repeat(number);
}
所以如果你这样做...
repeatString(3, 'Hey there! ');
你会得到:'嘿!嘿!嘿!'