我正在寻找以下方法的任何替代方法,以创建包含1到N的JavaScript数组,其中N仅在运行时已知。

var foo = [];

for (var i = 1; i <= N; i++) {
   foo.push(i);
}

对我来说,我觉得应该有一种不用循环的方法。


当前回答

我在寻找一个功能性的解决方案,最终得到了:

function numbers(min, max) {
  return Array(max-min+2).join().split(',').map(function(e, i) { return min+i; });
}

console.log(numbers(1, 9));

注意:join().split(',')将稀疏数组转换为连续数组。

其他回答

数组(…数组(9)).map((_,i)=>i);console.log(数组(…数组(9)).map((_,i)=>i))

使用ES6,您可以做到:

// `n` is the size you want to initialize your array
// `null` is what the array will be filled with (can be any other value)
Array(n).fill(null)

以下是摘要(在控制台中运行):

// setup:
var n = 10000000;
function* rangeIter(a, b) {
    for (let i = a; i <= b; ++i) yield i;
}
function range(n) { 
    let a = []
    for (; n--; a[n] = n);
    return a;
}
function sequence(max, step = 1) {
    return {
        [Symbol.iterator]: function* () {
            for (let i = 1; i <= max; i += step) yield i
        }
    }
}

var t0, t1, arr;
// tests
t0 = performance.now();
arr = Array.from({ length: n }, (a, i) => 1)
t1 = performance.now();
console.log("Array.from({ length: n }, (a, i) => 1) Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = range(n);
t1 = performance.now();
console.log("range(n) Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = Array.from(rangeIter(0, n));
t1 = performance.now();
console.log("Array.from(rangeIter(0, n)) Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = [...rangeIter(0, n)];
t1 = performance.now();
console.log("[...rangeIter(0, n)] Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = Array.from(sequence(n));
t1 = performance.now();
console.log("Array.from(sequence(n)) Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = [...sequence(n)];
t1 = performance.now();
console.log("[...sequence(n)] Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = Array(n).fill(0).map(Number.call, Number);
t1 = performance.now();
console.log("Array(n).fill(0).map(Number.call, Number) Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = Array.from(Array(n).keys());
t1 = performance.now();
console.log("Array.from(Array(n).keys()) Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = [...Array(n).keys()];
t1 = performance.now();
console.log("[...Array(n).keys()] Took " + (t1 - t0) + " milliseconds.");

最快的是Array(n).fill(0).map(Number.call,Number),第二个是[…Array(n).keys()]

但是。。。rangeIter的方式非常方便(可以内联),速度快,功能更强大

我发现了这条旧线索,因为我自己也在想同样的问题,但我想这里没有一个答案比Kokodoko评论的原始示例更容易,哈哈!

我最终自己使用了这个方法:

var foo = [];
while (foo.length < N)
    foo.push( foo.length + 1 );

这至少比常规的for循环稍微快一点,而且希望不容易出错(尽管在计算上可能更昂贵)。

甚至可以做以下事情:

var foo= [];
while (foo.length < N)
    foo.push( foo.length%4 + 1 );

以按顺序将阵列填充1-4次。或者使用此方法用单个项填充数组,尽管我想在这种情况下,只使用array(N).fill(x)可能会更快。

嗯,简单但重要的问题。Functional JS在Array对象下肯定缺少一个通用的展开方法,因为我们可能需要创建一个数字项数组,不仅是简单的[1,2,3,…,111],而且是一个函数产生的序列,可能是x=>x*2而不是x=>x

目前,要执行这项工作,我们必须依赖Array.prototype.map()方法。然而,为了使用Array.prototype.map(),我们需要提前知道数组的大小。还是。。如果我们不知道大小,那么我们可以使用Array.prototype.reduce(),但Array.protocol.reduce)用于缩小(折叠)而不是展开正确。。?

显然,我们需要函数JS中的Array.unfold()工具。这是我们可以简单地自己实现的;

Array.unfold = function(p,f,t,s){
  var res = [],
   runner = v =>  p(v,res.length-1,res) ? [] : (res.push(f(v)),runner(t(v)), res);
  return runner(s);
};

数组展开(p,f,t,v)采用4个参数。

p这是一个定义停止位置的函数。与许多数组函子一样,p函数接受3个参数。值、索引和当前生成的数组。它应返回布尔值。当它返回true时,递归迭代停止。f这是一个返回下一项函数值的函数。t这是一个函数,用于返回下一个参数,以便在下一个回合中提供给f。s是种子值,用于通过f计算索引0的舒适座椅。

因此,如果我们打算创建一个数组,其中包含一个像1,4,9,16,25…n^2这样的序列,我们可以简单地这样做。

Array.unfold=函数(p,f,t,s){var res=[],转轮=v=>p(v,res.length-1,res)?[]:(res.push(f(v)),runner(t(v),res);回流流道;};var myArr=数组展开((_,i)=>i>=9,x=>Math.pow(x,2),x=>x+1,1);console.log(myArr);