JavaScript 数组详解:从定义、创建到遍历,全面掌握数组的使用
JavaScript 中的数组(Array)是一种特殊的对象类型 ,用于存储多个值 ,并支持动态扩容、快速访问、遍历和操作。它是 JavaScript 中最基础、最常用的数据结构之一,掌握数组的使用对于前端开发至关重要。
一、什么是数组?
数组是一个有序的元素集合 ,每个元素都有一个索引(从 0 开始),可以通过索引快速访问数组中的元素。
数组的特性:
- 可遍历:可以使用多种方式遍历数组中的元素
- 动态扩容:可以随时添加或删除元素,数组大小自动调整
- 支持多种数据类型:数组中的元素可以是任意类型
- 具备对象特性:可以像对象一样设置键值对(但不推荐)
二、数组的创建方法
JavaScript 提供了多种方式来创建数组,每种方式都有其适用场景。
1. 使用字面量语法创建数组
javascript
const arr = [1, 2, 3]; // 创建一个包含3个元素的数组
- ✅ 语法简洁
- ✅ 可读性强
- ❌ 不适用于动态创建固定长度的数组
2. 使用构造函数 new Array()
javascript
const arr1 = new Array(5); // 创建一个长度为5的空数组([empty × 5])
const arr2 = new Array(1, 2, 3); // 创建数组 [1, 2, 3]
⚠️ 注意事项:
new Array(5)
并不会创建一个包含 5 个undefined
的数组,而是创建一个长度为 5 的"空数组",在for...in
遍历时不会触发任何迭代。- 如果你想创建一个可遍历的数组,可以使用:
javascript
const arr = new Array(5).fill(undefined); // [undefined, undefined, undefined, undefined, undefined]
empty不被当作属性,而undefined会被当做属性遍历
3. 使用静态方法创建数组
Array.of()
javascript
console.log(Array.of(1, 'a', 3)); // [1, "a", 3]
- 用途:将一组值转换为数组
- 特点:参数会直接作为数组元素
Array.from()
javascript
console.log(Array.from(new Array(26), (val, index) => String.fromCharCode(65 + index)));
// ['A', 'B', 'C', ..., 'Z']
- 用途:将类数组或可迭代对象转换为数组
- 支持映射函数 :可以配合
map
函数进行转换
三、数组的高级特性
1. 动态扩容
JavaScript 的数组是动态的,你可以随时添加或删除元素:
javascript
const arr = [1, 2];
arr[5] = 6; // 数组自动扩容,中间位置为 undefined
console.log(arr); // [1, 2, undefined, undefined, undefined, 6]
2. 支持 Hash 特性
JavaScript 数组本质上是对象,因此可以像对象一样设置键值:
javascript
const arr = [1, 2, 3];
arr['name'] = '数组'; // 合法,但不推荐
但要注意:这些自定义属性不会被 for...of
、map
等数组方法处理。
四、数组的遍历方法详解
遍历数组是 JavaScript 开发中最常见的操作之一。不同的遍历方式适用于不同的场景。
1. for
和 while
循环(基础遍历)
for
循环:
javascript
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
while
循环:
javascript
let i = 0;
while (i < arr.length) {
console.log(arr[i]);
i++;
}
- ✅ 性能好
- ✅ 可中断(
break
) - ❌ 可读性较差
- ✅ 适用于需要索引的场景
2. for...in
遍历(慎用)
javascript
for (const key in arr) {
console.log(key, arr[key]);
}
- ❌ 不推荐用于数组,因为会遍历原型链上的属性
- ✅ 适用于对象遍历
3. for...of
遍历(推荐)
javascript
for (const item of arr) {
console.log(item);
}
- ✅ 可读性好
- ✅ 可以结合
entries()
获取索引和值 - ✅ 推荐用于大多数数组遍历场景
获取索引和值:
javascript
for (const [index, value] of arr.entries()) {
console.log(index, value);
}
.entries()
方法说明:
arr.entries()
返回一个迭代器(Array Iterator
)- 每次迭代返回
[index, value]
的键值对 - 配合解构赋值
[index, value]
非常方便
4. forEach()
遍历
javascript
arr.forEach((item) => {
console.log(item);
});
- ✅ 可读性好
- ❌ 不能中断(不能
break
或return
) - ✅ 适用于"对每个元素执行操作"的场景
❗forEach
的坑:
- 不能提前中断 :即使你在回调中使用
return
,也只是跳过当前循环,不能停止整个遍历 - 不返回值:只用于执行副作用,不能用于筛选或映射
javascript
names.forEach(name => {
if (name === '张三') {
console.log('找到了');
return; // ❌ 只跳过当前循环,不能 break
}
console.log('继续找...');
});
5. 高阶函数遍历(map、filter、find、reduce 等)
这些方法不仅用于遍历数组,还能进行转换、筛选、查找等操作。
方法 | 用途 | 是否可中断 | 可读性 | 返回值 |
---|---|---|---|---|
map |
映射新数组 | ❌ | ✅ | 新数组 |
filter |
筛选符合条件的元素 | ❌ | ✅ | 新数组 |
find |
找到第一个符合条件的元素 | ✅ | ✅ | 元素或 undefined |
some |
判断是否有元素符合条件 | ✅ | ✅ | true 或 false |
every |
判断是否所有元素都符合条件 | ✅ | ✅ | true 或 false |
reduce |
累计计算 | ❌ | ❌ | 累计结果 |
6. reduce
方法详解
reduce
是数组中最强大的方法之一,用于将数组中的所有元素"归约"为一个值,比如求和、统计、合并等。
语法:
javascript
array.reduce((accumulator, currentValue) => {
// 返回新的 accumulator
}, initialValue);
示例:求和
javascript
const sum = [1, 2, 3, 4, 5, 6].reduce((prev, curr) => prev + curr, 0);
console.log(sum); // 21
示例:统计出现次数
javascript
const names = ['张三', '李四', '张三', '王五'];
const count = names.reduce((acc, name) => {
acc[name] = (acc[name] || 0) + 1;
return acc;
}, {});
console.log(count); // { 张三: 2, 李四: 1, 王五: 1 }
五、总结对比
方法 | 是否可中断 | 可读性 | 用途 |
---|---|---|---|
for |
✅ | ❌ | 基础遍历 |
while |
✅ | ❌ | 基础遍历 |
forEach |
❌ | ✅ | 对每个元素执行操作 |
map |
❌ | ✅ | 映射新数组 |
filter |
❌ | ✅ | 筛选符合条件的元素 |
find |
✅ | ✅ | 找到第一个符合条件的元素 |
some |
✅ | ✅ | 判断是否至少有一个元素符合条件 |
every |
✅ | ✅ | 判断是否所有元素都符合条件 |
reduce |
❌ | ❌ | 累计计算 |
for...of |
✅ | ✅ | 推荐的数组遍历方式 |
for...in |
✅ | ❌ | 适用于对象,慎用于数组 |
六、使用建议
- 优先使用
for...of
:可读性好,支持break
,适用于大多数数组遍历场景 - 需要索引时使用
entries()
:可以同时获取索引和值 - 使用
map
、filter
、reduce
等高阶函数:使代码更简洁、函数式 - 避免滥用
for...in
:容易遍历到原型链上的属性,不推荐用于数组 - 不要在数组中滥用对象特性:如设置非数字键值,避免混淆数据结构