如何使用 for in 循环动态填充数组

How to dynamically populate an array using a for in loop

为了 return 一个包含 1 到 500 之间的随机数序列的数组 set 我试图重构一个标准的 for 循环 for(var i = 0; i< 50; i++) 并且有效但是当我尝试这样做时使用 for in 循环的重构却没有。我的猜测是 array.length 属性 有一些问题,我搞砸了。

TL;DR 为什么这个 return 是一个包含 50 个未定义元素的数组而不是一个包含 50 个随机整数的数组?有没有办法让这种方法奏效?

var set = [];
set.length = 50;

for(var i in set){
    set[i] = Math.floor((Math.random() * 500) + 1);
}

console.log(set);

类似问题: 有帮助,但不是我想要的

更新

我怀疑我遗漏的一点是设置 set.length 不会向数组添加元素,它只会创建一个稀疏数组(一个有间隙的数组)。在我的例子中,你不能使用 for in 因为 in 数组中没有任何东西可以迭代。我要么必须用虚拟内容(即空字符串)填充数组,要么更逻辑地说,将我试图用 .length 属性 实现的范围部分分开到一个单独的 range 变量中.

工作版本

var set = [], range = 50;

for(var i = 0; i < range; i++){
    set[i]=Math.floor((Math.random() * 500) + 1);
}

console.log(set);

它 returns 未定义,因为您正在使用 set.length 设置数组长度。调用时,数组的所有元素都是 undefined

我会完全删除 set.length 行。

更新代码

var set = [];
for (i = 0; i <= 50; i++) {
  set.push(Math.floor(Math.random() * 500))
}

console.log(set)
=> [138, 215, 149, 180, 348, 497, 88, 156, 238, 439, 130, 185, 20, 116, 330, 131, 188, 257,
    260, 1, 469, 482, 208, 494, 26, 374, 281, 403, 403, 137, 156, 243, 378, 281, 329,
    84, 471, 429, 120, 381, 456, 471, 36, 395, 299, 497, 151, 210, 80, 310]

for in 似乎不是您想要的。尝试 for 循环:

var set = [], 
    i = 0, 
    l = null;

set.length = 50;

for(; l = set.length; i < l; i++){
    set[i] = Math.floor((Math.random() * 500) + 1);
}

console.log(set);

第二个link似乎有你的答案。

for (var item in array) 查看您的数组,对于数组中的每个项目,将该项目存储在 "item" 中并让您迭代每个项目。设置 array.length 不会给你数组中的任何项目,因此 for in 根本不会执行 - 没有什么可以迭代的。

我觉得您想创建一个包含动态内容的静态数组。如果是这种情况,您需要先创建具有适当大小的数组。那将为您创建数组。但是,您可以使用您想要的随机值自动填充数组,如下所示:

var N = 50;
var set = Array.apply(null, {length: N}).map(Function.call, Math.random);

数组自动填充后,您的代码的其余部分应该会按预期工作,只需使用数组中的随机数的值即可:

for(var i in set){
    set[i] = Math.floor(set[i] * 500) + 1;
}
console.log(set);
// OUTPUT
// [267, 219, 293, 298, 403, 70, 162, 270, 434, 292, 433, 478, 476, 
//  311, 268, 266, 105, 242, 255, 250, 206, 104, 142, 406, 50, 139, 
//  364, 375, 47, 480, 445, 149, 91, 228, 404, 267, 298, 158, 305, 
//  311, 92, 377, 490, 65, 149, 431, 28, 452, 353, 494]

这是我得到这个的地方:Create a JavaScript array containing 1...N

问题不在于 array.length 属性,而是这种扩大数组的方法不会创建 "properties." 请注意以下几点:

> [ /*hole*/ , /*hole*/ ,] // An array with two "holes"
[ ,  ]
> new Array(2) // Another way to create an array with two holes
[ ,  ]
> [ undefined, undefined ] // An array with two undefined elements -- not the same
[ undefined, undefined ]
> Object.getOwnPropertyNames([undefined, undefined]);
[ '0', '1', 'length' ]
> Object.getOwnPropertyNames([,,]);
[ 'length' ] // Doesn't have any integer properties!

您正在做的是创建一个包含零个元素的数组,然后将其扩展为包含 50 个 "holes,",就像带有两个孔的数组一样。由于此数组没有可枚举的属性(length 不可枚举),您无法使用 for...in 对其进行迭代。最终,您最好使用传统的 for 循环。

编辑

我能当场想到的 "hole" 的最佳定义是 一个不存在的 属性 数组,其名称是一个整数 i这样 0 <= i && i < array.length. (在考虑这一点时,重要的是要注意 JavaScript 数组只是具有称为 "indices" 的数字属性和一些额外的特殊功能的对象。)

属性 引用 return undefined 有两种方式:要么 属性 不存在,要么 属性 存在并包含值 undefined。因此:

> myObject = { myProp: 1, otherProp: undefined }
{ myProp: 1, otherProp: undefined }
> myObject.nonExistentProperty
undefined
> myObject.otherProp
undefined

现在,一个洞是不存在的 属性,就像上面的 myObject.nonExistentProperty,所以尝试访问它会导致它 return undefined.

用填充值填充数组的最好和最简单的方法可以简单地通过实例化 Array() class 然后使用 Array.protype.fill() 方法为其赋值来完成。

const array_filler = new Array(10).fill(20)

如需进一步参考,您可以阅读以下内容article