JavaScript Map:为什么这不起作用?

时间:2016-12-02 09:39:48

标签: javascript arrays

我试图使用地图生成一些随机数据。令我惊讶的是,我无法弄清楚为什么这段代码不起作用。

请考虑以下代码段,它按预期工作:

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

有人可以指出我在哪里错了吗?

4 个答案:

答案 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上的

forEachArray.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);

我们可以做的

Ori Drori points out

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())

你有一个包含两个未定义元素的数组。