new Array(n).map((_, index) => index) 不能初始化一个数组?

new Array(n) 将创建一个 n * undefined 的数组,那么为什么不能使用 new Array(n).map((_, index) => index) 函数得到 [0, 1, 2 ..., n-1] 这样的数组呢?

我知道 new Array(n).fill(0).map((_, index) => index) 这样是可以的,但 n * undefined 和 n * 0 的两个数组有本质区别吗?

阅读 4.3k
3 个回答
arrayLength传送门

If the only argument passed to the Array constructor is an integer between 0 and 2^32 - 1 (inclusive), this returns a new JavaScript array with its length property set to that number (Note: this implies an array of arrayLength empty slots, not slots with actual undefined values — see sparse arrays). If the argument is any other number, a RangeError exception is thrown.

一个范围在 0 到 2^32 - 1 之间的整数,此时将返回一个 length 的值等于 arrayLength 的数组对象(言外之意就是该数组此时并没有包含任何实际的元素,不能理所当然地认为它包含 arrayLength 个值为 undefined 的元素)。如果传入的参数不是有效值,则会抛出 RangeError 异常

Array(n) 或者 new Array(n) 生成的数组只有长度,没有元素,所以我称之为“幽灵数组”。这样的数组用 forEach 或者 map 等都不能正确遍历(因为没有元素),但很神奇的是它有 [@@iterator],可以使用 for ... of 遍历,也可以使用展开运算符来展开成数组(如 [...Array(10)]),更是可以使用 Array.from() 来转换。

所以生成数组的时候,有很多种方式。关于创建数组,参阅:JavaScript 数据处理 - 列表篇 | 八、创建数组


2024-05-08 补充
我知道 new Array(n).fill(0).map((_, index) => index) 这样是可以的,但 n undefined 和 n 0 的两个数组有本质区别吗?

这个问题涉及到 JavaScript 数组的数据结构,空槽 (slot) 和新旧两类方法对 slot 的处理。参考文档:

你那个 map 根本就不会被执行……

// 以下代码会打印出什么?注意别在 Array.prorotype.map 是 polyfill 出来的环境下执行
new Array(5).map((_, index) => console.log(index));

new Array(3) 是创建一个 length = 3、但是并没有 arr[0]、arr[1]、arr[2] 三个属性。注意是压根"没有",并不是"有、但值为 undefined",这点要注意区分。

// 以下代码又会打印出什么?
Object.keys(new Array(3));
Object.keys([undefined, undefined, undefined]);

自己动手试试就理解了。

别问为什么 new Array(n) 的表现为什么这么奇葩,问就是历史包袱,二十多年的 Bug 到今天也成 Feature 了。


扩展问题:

let arr1 = [];
arr1.length = 3;
// 上面代码和下面代码有什么不同?
let arr2 = [];
arr2.push(undefined);
arr2.push(undefined);
arr2.push(undefined);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题