一.核心概念
JavaScript 数组(Array)是有序的复合数据类型,用于存储多个不同类型的值(数字、字符串、对象等),支持动态扩容 / 缩容,且提供了丰富的内置方法,是 JS 中最常用的数据结构之一.
二.数组的创建
1.字面量方式(最推荐)
简洁直观,日常开发首选:
javascript
// 空数组
const arr1 = [];
// 存储不同类型的值
const arr2 = [10, 'hello', true, { name: '张三' }, [1, 2, 3]];
// 稀疏数组(不推荐,存在空槽)
const arr3 = [1, , 3]; // 索引1为空
2.构造函数方式(new Array())
灵活但需注意特殊情况:
javascript
// 1. 无参数:创建空数组(等同于 [])
const arr4 = new Array();
// 2. 单个数字参数:创建指定长度的空数组(仅初始化长度,无实际元素)
const arr5 = new Array(5); // [empty × 5],长度为5,无真实元素
// 3. 多个参数:创建包含这些元素的数组
const arr6 = new Array(10, 20, 30); // [10, 20, 30]
3.其他创建方式
I.Array.of():
统一处理参数(避免单个数字参数的歧义)
javascript
Array.of(5); // [5](不同于 new Array(5))
Array.of(10, 20, 30); // [10, 20, 30](等同于字面量)
II.Array.from():
将类数组 / 可迭代对象(如字符串、NodeList)转为数组
javascript
Array.from('abc'); // ["a", "b", "c"]
Array.from([1, 2, 3], (item) => item * 2); // [2, 4, 6](支持映射函数)
三.数组的核心特性
有序性:元素按索引(从 0 开始)排列,可通过索引访问/修改动态长度:无需预先指定长度,添加/删除元素时长度自动变化异质性:可存储不同类型的值(数字、字符串、对象、函数等)本质是对象:数组的typeof结果为object,但有专门的Array.isArray()判断
四.数组的基础操作
1.访问 / 修改元素
通过索引操作(索引越界返回 undefined):
javascript
const arr = [10, 20, 30];
// 访问元素
console.log(arr[0]); // 10(第一个元素)
console.log(arr[2]); // 30(第三个元素)
console.log(arr[3]); // undefined(索引越界)
// 修改元素
arr[1] = 200;
console.log(arr); // [10, 200, 30]
// 新增元素(直接赋值,数组长度自动扩容)
arr[3] = 40;
console.log(arr); // [10, 200, 30, 40](长度变为4)
2.数组长度(length)
读取 : arr.length 返回数组元素个数
修改 : 手动设置 length 可扩容 / 缩容(缩容会删除超出长度的元素)
javascript
const arr = [10, 20, 30];
console.log(arr.length); // 3
// 缩容:删除索引 ≥2 的元素
arr.length = 2;
console.log(arr); // [10, 20]
// 扩容:新增空槽(不推荐,尽量用 push 等方法)
arr.length = 5;
console.log(arr); // [10, 20, empty × 3]
3.新增元素(常用方法)
| 方法 | 功能 | 原数组是否改变 |
|---|---|---|
push(elem) |
尾部添加一个 / 多个元素,返回新长度 | 是 |
unshift(elem) |
头部添加一个 / 多个元素,返回新长度 | 是 |
splice(index, 0, elem) |
任意位置插入元素(0 表示不删除) | 是 |
示例:
javascript
const arr = [10, 20];
// push:尾部新增
arr.push(30, 40);
console.log(arr); // [10, 20, 30, 40]
// unshift:头部新增
arr.unshift(0);
console.log(arr); // [0, 10, 20, 30, 40]
// splice:索引 2 插入 15
arr.splice(2, 0, 15);
console.log(arr); // [0, 10, 15, 20, 30, 40]
4.删除元素(常用方法)
| 方法 | 功能 | 原数组是否改变 |
|---|---|---|
pop() |
尾部删除一个元素,返回删除的元素 | 是 |
shift() |
头部删除一个元素,返回删除的元素 | 是 |
splice(index, num) |
从 index 开始删除 num 个元素,返回删除的元素数组 |
是 |
filter() |
过滤元素(保留满足条件的),返回新数组 | 否(纯函数) |
示例:
javascript
const arr = [0, 10, 15, 20, 30, 40];
// pop:尾部删除
const last = arr.pop();
console.log(last); // 40,arr 变为 [0, 10, 15, 20, 30]
// shift:头部删除
const first = arr.shift();
console.log(first); // 0,arr 变为 [10, 15, 20, 30]
// splice:索引 1 开始删除 2 个元素
const deleted = arr.splice(1, 2);
console.log(deleted); // [15, 20],arr 变为 [10, 30]
// filter:保留大于 15 的元素(原数组不变)
const newArr = arr.filter((item) => item > 15);
console.log(newArr); // [30],arr 仍为 [10, 30]
五.数组的核心内置方法(按用途分类)
1.遍历 / 迭代(不改变原数组)
| 方法 | 功能 | 返回值 |
|---|---|---|
forEach((item, index, arr) => {}) |
遍历每个元素,无返回值 | undefined |
map((item) => {}) |
遍历并映射元素,返回新数组 | 映射后的新数组 |
filter((item) => {}) |
过滤元素,保留返回 true 的元素 | 过滤后的新数组 |
find((item) => {}) |
查找第一个满足条件的元素 | 找到则返回元素,否则 undefined |
findIndex((item) => {}) |
查找第一个满足条件的元素索引 | 找到则返回索引,否则 -1 |
every((item) => {}) |
判断所有元素是否满足条件 | true/false(短路求值) |
some((item) => {}) |
判断是否有至少一个元素满足条件 | true/false(短路求值) |
reduce((acc, item) => {}, init) |
累加 / 归约,将数组转为单个值 | 最终累加结果 |
示例:
javascript
const arr = [1, 2, 3, 4, 5];
// forEach:遍历
arr.forEach((item, index) => {
console.log(`索引${index}:${item}`); // 依次输出 1-5
});
// map:映射(每个元素 ×2)
const doubleArr = arr.map(item => item \* 2);
console.log(doubleArr); // [2, 4, 6, 8, 10]
// filter:过滤偶数
const evenArr = arr.filter(item => item % 2 === 0);
console.log(evenArr); // [2, 4]
// find:找第一个大于 3 的元素
const found = arr.find(item => item > 3);
console.log(found); // 4
// reduce:求和(init 为 0,acc 是累加器)
const sum = arr.reduce((acc, item) => acc + item, 0);
console.log(sum); // 15
2.排序 / 反转(改变原数组)
reverse():反转数组顺序
sort((a, b) => {}):排序(默认按字符串 Unicode 排序,需自定义比较函数)
示例:
javascript
const arr = [3, 1, 4, 1, 5];
// 反转
arr.reverse();
console.log(arr); // [5, 1, 4, 1, 3]
// 排序:默认字符串排序(错误,如 10 会排在 2 前面)
arr.sort();
console.log(arr); // [1, 1, 3, 4, 5](巧合正确,数字排序需自定义)
// 数字升序(a - b)
arr.sort((a, b) => a - b);
console.log(arr); // [1, 1, 3, 4, 5]
// 数字降序(b - a)
arr.sort((a, b) => b - a);
console.log(arr); // [5, 4, 3, 1, 1]
3.数组拼接 / 截取(不改变原数组)
concat(arr1, arr2...):拼接多个数组 / 元素,返回新数组
slice(start, end):截取从 start 到 end(不包含 end)的元素,返回新数组
start:起始索引(负数表示从尾部开始,如 -2 表示倒数第二个)
end:结束索引(可选,默认到数组末尾)
示例:
javascript
const arr1 = [1, 2];
const arr2 = [3, 4];
// concat:拼接
const newArr = arr1.concat(arr2, 5);
console.log(newArr); // [1, 2, 3, 4, 5],arr1/arr2 不变
// slice:截取
const arr = [10, 20, 30, 40, 50];
console.log(arr.slice(1, 3)); // [20, 30](索引1-2)
console.log(arr.slice(2)); // [30, 40, 50](索引2到末尾)
console.log(arr.slice(-2)); // [40, 50](倒数第二个到末尾)
4.其他常用方法
| 方法 | 功能 | 返回值 | 原数组是否改变 |
|---|---|---|---|
includes(elem) |
判断数组是否包含指定元素 | true/false |
否 |
indexOf(elem) |
查找元素第一次出现的索引 | 索引 /-1 |
否 |
lastIndexOf(elem) |
查找元素最后一次出现的索引 | 索引 /-1 |
否 |
join(sep) |
将数组元素拼接为字符串(sep 为分隔符) |
拼接后的字符串 | 否 |
flat(depth) |
扁平化数组(depth 为扁平化深度,默认 1) |
扁平化后的新数组 | 否 |
示例:
javascript
const arr = [1, 2, 3, 2, [4, [5]]];
// includes:是否包含 2
console.log(arr.includes(2)); // true
// indexOf:找 2 第一次出现的索引
console.log(arr.indexOf(2)); // 1
// join:用"-"拼接
console.log(arr.join('-')); // "1-2-3-2-4,5"
// flat:扁平化(depth=2 彻底扁平化)
const flatArr = arr.flat(2);
console.log(flatArr); // [1, 2, 3, 2, 4, 5]
六.常用场景示例
1.数组去重
javascript
const arr = [1, 2, 2, 3, 3, 3];
// 方法 1:Set 去重(简洁)
const uniqueArr1 = [...new Set(arr)];
// 方法 2:filter 去重(保留第一个出现的元素)
const uniqueArr2 = arr.filter((item, index) => arr.indexOf(item) === index);
console.log(uniqueArr1); // [1, 2, 3]
2.数组求和 / 求平均值
javascript
const arr = [1, 2, 3, 4, 5];
// 求和
const sum = arr.reduce((acc, item) => acc + item, 0);
// 求平均值
const avg = sum / arr.length;
console.log(sum); // 15,avg:3
3.多维数组扁平化
javascript
const arr = [1, [2, [3, [4]]]];
// 彻底扁平化(depth=Infinity)
const flatArr = arr.flat(Infinity);
console.log(flatArr); // [1, 2, 3, 4]
4.对象数组排序(按指定字段)
javascript
const users = [
{ name: '张三', age: 25 },
{ name: '李四', age: 20 },
{ name: '王五', age: 30 }
];
// 按 age 升序
users.sort((a, b) => a.age - b.age);
console.log(users); // 李四(20)→ 张三(25)→ 王五(30)
七.数组的注意事项
避免稀疏数组: 空槽(empty)在遍历(如forEach)时会被跳过,容易引发 bug,尽量用正常元素填充.- 区分 "改变原数组" 和 "返回新数组":
- 改原数组:
push/pop/shift/unshift/splice/sort/reverse - 返新数组:
map/filter/concat/slice/flat/Array.from
- 改原数组:
- typeof 判断数组不准确:
typeof [] === "object",需用Array.isArray(arr)判断是否为数组. - sort 排序的坑: 默认按字符串排序,数字排序必须传入比较函数
(a, b) => a - b(升序)或(a, b) => b - a(降序).