我正在寻找以下任何替代方案,以创建包含 1 到 N 的 JavaScript 数组,其中 N 仅在运行时已知。
var foo = [];
for (var i = 1; i <= N; i++) {
foo.push(i);
}
对我来说,感觉应该有一种没有循环的方法。
我正在寻找以下任何替代方案,以创建包含 1 到 N 的 JavaScript 数组,其中 N 仅在运行时已知。
var foo = [];
for (var i = 1; i <= N; i++) {
foo.push(i);
}
对我来说,感觉应该有一种没有循环的方法。
在 ES6 中使用 Array from()和keys()方法。
Array.from(Array(10).keys())
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
使用扩展运算符的较短版本。
[...Array(10).keys()]
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
从 1 开始,将 map 函数传递给 Array from(),并带有一个具有length
属性的对象:
Array.from({length: 10}, (_, i) => i + 1)
//=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
你可以这样做:
var N = 10;
Array.apply(null, {length: N}).map(Number.call, Number)
结果:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
或随机值:
Array.apply(null, {length: N}).map(Function.call, Math.random)
导致:[0.7082694901619107,0.9572225909214467,0.8586748542729765,0.8653848143294454,0.008339877473190427,0.9911756622605026,0.8133423360995948,0.8377588465809822,0.5577575915958732,0.16363654541783035]
首先,请注意,Number.call(undefined, N)
它等价于Number(N)
,它只返回N
。我们稍后会用到这个事实。
Array.apply(null, [undefined, undefined, undefined])
等价于Array(undefined, undefined, undefined)
,它生成一个三元素数组并分配undefined
给每个元素。
您如何将其推广到N 个元素?考虑如何Array()
工作,它是这样的:
function Array() {
if ( arguments.length == 1 &&
'number' === typeof arguments[0] &&
arguments[0] >= 0 && arguments &&
arguments[0] < 1 << 32 ) {
return [ … ]; // array of length arguments[0], generated by native code
}
var a = [];
for (var i = 0; i < arguments.length; i++) {
a.push(arguments[i]);
}
return a;
}
从 ECMAScript 5 开始,Function.prototype.apply(thisArg, argsArray)
也接受一个类似鸭子类型的数组对象作为它的第二个参数。如果我们调用Array.apply(null, { length: N })
,那么它将执行
function Array() {
var a = [];
for (var i = 0; i < /* arguments.length = */ N; i++) {
a.push(/* arguments[i] = */ undefined);
}
return a;
}
现在我们有一个N元素数组,每个元素都设置为undefined
。当我们调用.map(callback, thisArg)
它时,每个元素都会被设置为 的结果callback.call(thisArg, element, index, array)
。因此,[undefined, undefined, …, undefined].map(Number.call, Number)
会将每个元素映射到(Number.call).call(Number, undefined, index, array)
,这与 相同Number.call(undefined, index, array)
,正如我们之前观察到的,评估为index
。这完成了其元素与其索引相同的数组。
为什么要经历麻烦Array.apply(null, {length: N})
而不是仅仅Array(N)
?毕竟,这两个表达式都会产生一个包含未定义元素的N元素数组。区别在于,在前一个表达式中,每个元素都显式设置为 undefined,而在后者中,每个元素都从未设置过。根据以下文件.map()
:
callback
仅对已分配值的数组索引调用;不会为已删除或从未分配值的索引调用它。
因此,Array(N)
是不够的;Array(N).map(Number.call, Number)
将导致长度为N的未初始化数组。
由于此技术依赖Function.prototype.apply()
于 ECMAScript 5中指定的行为,因此它不适用于 ECMAScript 5 之前的浏览器,例如 Chrome 14 和 Internet Explorer 9。
...
) 和键方法[ ...Array(N).keys() ].map( i => i+1);
Array(N).fill().map((_, i) => i+1);
Array.from(Array(N), (_, i) => i+1)
{ length: N }
hackArray.from({ length: N }, (_, i) => i+1)
所有上述形式通过改变初始化为几乎任何期望的值可以产生阵列i+1
所需表达(例如i*2
,-i
,1+i*2
,i%2
和等等)。如果表达式可以用某个函数表示,f
那么第一种形式就变得简单了
[ ...Array(N).keys() ].map(f)
Array.from({length: 5}, (v, k) => k+1);
// [1,2,3,4,5]
由于数组undefined
在每个位置上初始化, 的值v
将是undefined
f
即[ ...Array(N).keys() ].map((i) => f(i))
甚至更简单
[ ...Array(N).keys() ].map(f)
如果我得到你想要的东西,你需要一个数字数组1..n
,你可以稍后循环。
如果这就是你所需要的,你可以这样做吗?
var foo = new Array(45); // create an empty array with length 45
那么当你想使用它时......(未优化,仅举个例子)
for(var i = 0; i < foo.length; i++){
document.write('Item: ' + (i + 1) + ' of ' + foo.length + '<br/>');
}
例如,如果你不需要在数组中存储任何东西,你只需要一个长度合适的容器,你可以迭代......这可能更容易。
在这里查看它的实际效果:http : //jsfiddle.net/3kcvm/
数组天生管理它们的长度。当它们被遍历时,它们的索引可以保存在内存中并在那时被引用。如果需要知道随机索引,indexOf
可以使用该方法。
这就是说,根据您的需要,您可能只想声明一个特定大小的数组:
var foo = new Array(N); // where N is a positive integer
/* this will create an array of size, N, primarily for memory allocation,
but does not create any defined values
foo.length // size of Array
foo[ Math.floor(foo.length/2) ] = 'value' // places value in the middle of the array
*/
利用扩展运算符 ( ...
) 和keys
方法,您可以创建一个大小为 N 的临时数组来生成索引,然后创建一个可以分配给变量的新数组:
var foo = [ ...Array(N).keys() ];
您可以首先创建所需数组的大小,用 undefined 填充它,然后使用 来创建一个新数组map
,它将每个元素设置为索引。
var foo = Array(N).fill().map((v,i)=>i);
这应该初始化为大小为 N 的长度并一次性填充数组。
Array.from({ length: N }, (v, i) => i)
代替评论和混淆,如果您真的想从上述示例中的 1..N 中获取值,有几个选项:
++i
)。 在不使用索引的情况下——可能还有一种更有效的方法——是创建你的数组,但让 N 代表 N+1,然后从前面移开。
所以如果你想要 100 个数字:
let arr; (arr=[ ...Array(101).keys() ]).shift()