为什么我不能使用 _.map(new Array(n), Math.random) 创建一个随机数组

Why can't I create a random array using _.map(new Array(n), Math.random)?

本文关键字:random Math 创建 数组 随机 一个 不能 Array new map 为什么      更新时间:2023-09-26

我想制作一个介于 0 和 1 之间的随机数数组,所以我尝试了:

var randList = _.map(new Array(5), Math.random);

但是我没有获得我期望的随机元素列表,而是得到了:

console.log(JSON.stringify(randList));
"[null,null,null,null,null]"

为什么我得到一个空数组而不是随机数?

实际上,你会得到一个undefined数组 - 传递给map的函数甚至一次都不会触发。发生这种情况是因为使用构造函数创建的数组new Array(Number)有点奇怪 - 即使它的长度设置正确,它实际上也没有01等属性:

var arr = Array(5);
console.log(arr.length); // 5
console.log('0' in arr); // false

这就是为什么,即使普通的旧for (var i = 0; i < arr.length; i++)可以迭代这个数组,for (var i in arr)也不起作用:

for (var i in arr) {
   console.log(i); // won't be called even once!
}

我想,这与 Array.map 发生的情况(映射 _.map 时)的情况不太相似:

var newarr = arr.map(function(el) {
   console.log(el); // nope, still nothing
});
console.log(newarr); // [undefined x 5]

那么创建这样一个数组的正确方法是什么?在这里:

var rightArr = Array.apply(0, Array(5)); // ah, the pure magic of apply!
// and here goes an array of randoms:
var randArr = rightArr.map(Math.random);

。但当然,在这种情况下,使用_.times是要走的路。)

Array(length)构造函数创建一个稀疏数组。也就是说,数组的长度设置为指定的参数,但不填充数组的元素。因此,map方法不会循环访问这些"未填充"元素。例如,以下代码片段不会在控制台上生成任何输出:

var arr = new Array(5);
for(var x in arr) console.log(x);

但是请注意,像这样初始化数组将产生预期的结果:

console.log(_.map([0,0,0,0,0], Math.random));

当然,这不会扩展。如果您希望数组中的元素数量是可变的,我建议您改用 times 方法:

var randList = _(5).times(Math.random);

var randList = _.times(5, Math.random);

只是想在raina77ow的出色答案中添加一些测试用例。

事实上,新的 Array(5) 不会在 Array 对象中分配 5 个属性。

无论你使用下划线还是普通的javascript Array.prototype.map(当然是在体面的浏览器中)都没有关系。

以下是节点中的测试用例.js

new Array(2)

只返回一个空对象(没有键),带有 2 个(一种假的)占位符

> var a = new Array(2);
> a;
[ ,  ]
> a.length;
2
> Object.keys(a);
[]

映射结果也是一个带有 2 个占位符的空对象(无键)

> var result = a.map(Math.random);
> result;
[ ,  ]
> result.length;
2
> Object.keys(result);
[]

为什么结果是一个长度为 2 的数组对象,即使什么也没做?

阅读 Array.prototype.map polyfill implmentation https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

地图结果创建为 var res = new Array(source_array_length);

此外,即使值undefined,映射也适用于填充数组

> [undefined, undefined].map(Math.random);
[ 0.6572469582315534, 0.6343784828204662 ]

好的,让我们也测试稀疏数组,长度为 2,但它只包含一个键"1"。

> var a = []; a[1] = 'somthing';
> a;
[ , 'somthing' ]
> a.length
2
> Object.keys(a);
[ '1' ]

映射结果返回一个长度为 2 的数组,但只有一个键 '1',只触发一个 Math.random!

> var result = a.map(Math.random);
undefined
> result.length
2
> result
[ , 0.8090629687067121 ]  // only one Math.random fired.
> Object.keys(result);
[ '1' ]