JS 数组初始化的两种方式:空槽(hole) vs undefined。 下面从结果结构、可遍历性、行为差异、使用场景几个维度,系统对比
一、最直观的差异(重点)
js
new Array(10)
// [ <10 empty items> ]
Array.from({ length: 10 })
// [ undefined, undefined, ..., undefined ](10 个)
核心区别:
new Array(10)→ 稀疏数组(holes)Array.from({ length: 10 })→ 密集数组(元素存在,值为 undefined)
二、数组"空槽(hole)" vs undefined
| 特性 | new Array(10) | Array.from({ length: 10 }) |
|---|---|---|
| 数组长度 | 10 | 10 |
| 是否有元素 | ❌ 没有(hole) | ✅ 有 |
0 in arr |
false | true |
arr[0] |
undefined | undefined |
| JSON.stringify | [null,null,...] |
[null,null,...] |
js
const a = new Array(10)
const b = Array.from({ length: 10 })
// 检查0下标
0 in a // false
0 in b // true
⚠️
undefined !== hole
三、遍历 & 高阶函数行为差异(非常重要)
1️⃣ map / forEach / filter
js
new Array(3).map(() => 1)
// [ <3 empty items> ]
Array.from({ length: 3 }).map(() => 1)
// [1, 1, 1]
原因:
- 高阶方法会 跳过 hole
- 不会跳过
undefined
2️⃣ for...of
js
for (const x of new Array(3)) {
console.log(x)
}
// undefined undefined undefined
for (const x of Array.from({ length: 3 })) {
console.log(x)
}
// undefined undefined undefined
for...of会遍历 hole(与 map 不同)
3️⃣ for...in
js
for (const i in new Array(3)) console.log(i)
// 什么都不输出
for (const i in Array.from({ length: 3 })) console.log(i)
// 0 1 2
四、性能与语义差异
| 维度 | new Array(10) | Array.from({ length: 10 }) |
|---|---|---|
| 创建速度 | 更快 | 稍慢 |
| 内存 | 更省(无元素) | 占用更多 |
| 可预测性 | ❌ 容易踩坑 | ✅ 行为一致 |
| 函数式友好 | ❌ | ✅ |
五、典型使用场景
✅ 适合 new Array(10) 的情况
js
// 只关心 length
const buffer = new Array(1024)
// 之后立即填充
const arr = new Array(10)
arr.fill(0)
✅ 适合 Array.from({ length: 10 })
js
// 需要 map / filter / reduce
const list = Array.from({ length: 10 }, (_, i) => i)
// JSX / Vue 渲染
{Array.from({ length: 5 }).map((_, i) => (
<Item key={i} />
))}
六、等价但更常见的写法
js
Array.from({ length: 10 }, (_, i) => i)
// 等价于
[...Array(10).keys()]
七、总结一句话(面试 / 设计建议)
new Array(n)创建的是"空槽数组",
Array.from({ length: n })创建的是"真实元素数组"。
推荐原则:
- 要 遍历 / map / 渲染 →
Array.from - 只当 占位容器 →
new Array