new Array(5) 创建长度为5的稀疏数组,无实际元素,map/forEach不遍历;要稠密数组需用Array.from({length:5})或fill();字面量[]更安全高效。

Array 构造函数传一个数字参数会创建稀疏数组
直接写 new Array(5) 不是创建包含 5 个 undefined 的数组,而是创建长度为 5、但没有任何实际元素的稀疏数组(sparse array)。它的 length 是 5,但 0 in arr 返回 false,JSON.stringify(arr) 得到 [null,null,null,null,null] —— 注意不是 undefined,序列化时被转成 null。
常见误用场景:想初始化一个 5 元素的空数组用于后续赋值,结果发现 map、forEach 完全不遍历它,因为这些方法跳过稀疏位置。
- 要得到真正含 5 个
undefined的数组,用Array.from({ length: 5 })或Array(5).fill(undefined) -
new Array(1, 2, 3)是安全的,此时它等价于字面量[1, 2, 3],不会产生稀疏问题 - 传入非整数(如
new Array('3'))会创建单元素数组['3'],不是长度为 3 的数组
字面量 [] 总是创建稠密数组,但不能动态控制长度
写 [1, 2, 3] 或 [] 创建的数组一定是稠密的,每个索引位置都存在(哪怕值是 undefined),map、filter 等方法能正常工作。但它无法像 new Array(n) 那样仅靠参数声明长度 —— 你不能写 [...n] 来生成 n 个元素(除非用扩展运算符配合 Array.from)。
- 想快速生成 [0,1,2,3,4]?用
Array.from({ length: 5 }, (_, i) => i),别用new Array(5).map((_, i) => i)—— 后者返回空数组 - 字面量里写
[,,](两个连续逗号)会产生稀疏数组,和new Array(2)效果一致,要小心 -
[undefined, undefined]是稠密的:两个位置都有值(尽管值是undefined),forEach会执行两次
Array 构造函数在子类继承中行为不同
如果定义了继承自 Array 的子类(比如 class MyArray extends Array {}),用 new MyArray(3) 创建实例时,内部仍会调用父类逻辑,结果是稀疏数组;但 new MyArray(1, 2, 3) 或 MyArray.of(1, 2, 3) 就能正确构造稠密子类实例。
- 子类应优先用
MyArray.of()替代new MyArray(),避免稀疏陷阱 -
Array.from()返回的是普通Array实例,不是子类实例;若需子类实例,得用MyArray.from()(前提是子类实现了静态from方法或继承了它) - ES6+ 中
Array()作为函数调用(不加new)等价于new Array(),行为完全一致
性能与可读性:字面量几乎总是更优选择
除了极少数需要预分配大数组长度(且确定后续会填满)的场景,[] 字面量比 new Array() 更快、更直观、更少歧义。V8 等引擎对字面量有深度优化,而 new Array(n) 在多数情况下反而触发慢路径。
- 构建空数组?无条件用
[] - 初始化已知元素?用
[a, b, c],别写new Array(a, b, c) - 需要指定长度并填充默认值?用
Array(n).fill(value),而不是new Array(n)后再循环赋值 - 动态长度 + 动态内容?
Array.from({ length: n }, fn)是最清晰、最可靠的模式
稀疏数组的存在本身就是一个历史包袱,现代代码里主动制造它几乎没有正当理由;一旦出现“数组长度不对”“遍历不到元素”之类问题,先检查是不是误用了单参数 new Array()。

















