我试图使用地图生成一些随机数据。令我惊讶的是,我无法弄清楚为什么这段代码不起作用。
请考虑以下代码段,它按预期工作:
const empty = [undefined, undefined];
const rand = empty.map(item => Math.random());
Output: [0.4774752874308936, 0.8482276976659398]
我试图简化一下并执行以下操作
const rand = Array(2).map(item => Math.random())
Output: [undefined × 2]
我无法理解为什么会这样。很明显,Array(n)和[]生成的两个数组都是典型的数组,并且都有原型方法。
Array(2) instanceof Array
true
[undefined, undefined] instanceof Array
true
Array.isArray(Array(2))
true
Array.isArray([undefined, undefined])
true
有人可以指出我在哪里错了吗?
答案 0 :(得分:21)
Array(2)
为您提供长度为2
的空数组。 JavaScript数组本质上是稀疏(它们可以有空洞,因为they aren't really arrays at all¹),这就是Array(2)
给你的。它看起来像这样:
+−−−−−−−−−−−−−−+ | (array) | +−−−−−−−−−−−−−−+ | length: 2 | +−−−−−−−−−−−−−−+
而你的[undefined, undefined]
数组看起来像这样:
+−−−−−−−−−−−−−−+ | (array) | +−−−−−−−−−−−−−−+ | length: 2 | | 0: undefined | | 1: undefined | +−−−−−−−−−−−−−−+
map
上的 forEach
,Array.prototype
和大多数(但不是全部)相关方法仅循环通过实际条目稀疏数组。由于Array(2)
返回的数组没有任何实际条目,因此永远不会调用您的回调。
ES2015添加Array#fill
(并且可以填充),您可以使用它来填充数组:
const rand = Array(2).fill().map(Math.random)
console.log(rand);
(请注意,由于Me.Name pointed out我们不需要item => Math.random
,我们可以直接致电Math.random
;它不会使用this
或其undefined
参数(spec)。)
还有一个技巧可以创建一个带有const empty = [...Array(2)]:
的填充数组:
fill
...如果你不想要const rand = [...Array(2)].map(Math.random);
console.log(rand);
,你可以这样申请:
Array.from({length: 2}, Math.random);
我们可以做的
const rand = Array.from({length: 2}, Math.random);
console.log(rand);
e.g:
Array.apply(null, {length: 2}).map(Math.random);
Nina Scholz adds经典,与ES5兼容:
var rand = Array.apply(null, {length: 2}).map(Math.random);
console.log(rand);
key
¹(这是我贫血的小博客上的帖子)
答案 1 :(得分:4)
您可以查看Array#map
的规范:
不会调用数组中缺少的元素(即,从未设置过的索引,已删除的索引或从未赋值的索引)。
您可以使用Array.apply获取带有map的iterabel数组。
console.log(Array.apply(null, { length: 2 }).map(Math.random));
答案 2 :(得分:4)
那是因为您认为Array(2)
被JavaScript引擎解释为:"创建一个数组对象,其中两个条目初始化为默认值,比如说0或{{1 }}"
实际上,JavaScript引擎会创建一个新对象并将其undefined
属性设置为2.它没有任何实际内容。
检查这个非常简单的例子:
length

如果您运行它并检查控制台,您将会看到类似这样的内容:
var arr = new Array(2);
console.log(arr);
没有内容,没有占位符。只是一个Array[2] => {
length: 2,
__proto__: Array[0]
}
初始化为2的空数组。
这就是你的箭头函数永远不会被调用的原因。
答案 3 :(得分:-1)
您正在创建一个初始化为大小为2的数组。但是这些位置中没有任何元素。然后你做了
[undefined, undefined].map(item => Math.random())
你有一个包含两个未定义元素的数组。