重要分类

  • 改变原数组splicereversesortpushpopshiftunshiftfill
  • 不改变原数组mapfiltersliceconcatjoinreduce

一、ES5 数组方法

1.1 查找与检测

indexOf() - 查找元素索引

语法 array.indexOf(searchElement[, fromIndex])

const list = [1, 2, 3];
 
list.indexOf(2);   // 1
list.indexOf("蛙人");  // -1(不存在)
list.indexOf(2, 2);    // -1(从索引2开始查找)

Array.isArray() - 检测数组

Array.isArray([1, 2, 3]);  // true
Array.isArray("not array"); // false

1.2 遍历与转换

map() - 映射数组

回调参数

  • value - 当前元素值
  • index - 当前索引
  • self - 原数组本身
const list = [1, 2, 3];
 
const res = list.map((value, index, self) => {
  console.log(value); // 1 2 3
  console.log(index); // 0 1 2
  console.log(self);  // [1, 2, 3]
  return value * 2;
});
 
console.log(res);   // [2, 4, 6]
console.log(list);  // [1, 2, 3](原数组不变)

forEach() - 遍历数组

const list = [1, 2, 3];
 
const res = list.forEach((value, index, self) => {
  console.log(value); // 1 2 3
  console.log(index); // 0 1 2
  console.log(self);  // [1, 2, 3]
  return 123;  // 返回值无效
});
 
console.log(res);  // undefined

forEach 特点

  • 返回值总是 undefined
  • 只读操作,不能中断(使用 breakreturn 无效)
  • 性能比普通 for 循环差

filter() - 过滤数组

const list = [1, 2, 3];
const res = list.filter((item) => item > 1);
 
console.log(res);   // [2, 3]
console.log(list);  // [1, 2, 3](原数组不变)

reduce() - 累加器

语法 array.reduce(callback[, initialValue])

参数说明
prev初始值或上一次计算结果
cur当前元素
index当前索引
self原数组
const list = [1, 2, 3];
 
// 求和
const sum = list.reduce((prev, cur) => prev + cur, 0);
console.log(sum);  // 6
 
// 求最大值
const max = list.reduce((prev, cur) => Math.max(prev, cur));
console.log(max);  // 3
 
// 数组去重
const arr = [1, 2, 2, 3];
const unique = arr.reduce((prev, cur) => {
  return prev.includes(cur) ? prev : [...prev, cur];
}, []);
console.log(unique);  // [1, 2, 3]

1.3 条件检测

every() - 全部满足

const list = [1, 2, 3];
 
list.every((item) => item > 0);  // true(全部大于0)
list.every((item) => item > 1);  // false(不全部大于1)

some() - 部分满足

const list = [1, 2, 3];
 
list.some((item) => item > 2);  // true(有元素大于2)
list.some((item) => item > 5);  // false(没有元素大于5)

1.4 操作与截取

splice() - 删除/替换(改变原数组)

改变原数组 array.splice(start[, deleteCount[, item1[, item2[, ...]]]])

参数说明
start开始位置
deleteCount删除数量(0则不删除)
items要添加的元素
let list = [1, 2, 3];
 
// 删除
list.splice(0, 1);          // 删除第0位,删除1位
console.log(list);          // [2, 3]
 
// 替换
list.splice(0, 1, "蛙人");  // 删除第0位,添加"蛙人"
console.log(list);          // ["蛙人", 2, 3]
 
// 插入
list.splice(1, 0, "新元素"); // 不删除,在第1位插入
console.log(list);          // ["蛙人", "新元素", 2, 3]

slice() - 截取数组(不改变原数组)

const list = [1, 2, 3, 4, 5];
 
// 从索引1截取到索引3(不包含3)
const res = list.slice(1, 3);
console.log(res);   // [2, 3]
console.log(list);  // [1, 2, 3, 4, 5]
 
// 从索引2截取到末尾
const res2 = list.slice(2);
console.log(res2);  // [3, 4, 5]
 
// 截取最后2个
const res3 = list.slice(-2);
console.log(res3);  // [4, 5]

1.5 修改与排序

reverse() - 反转数组(改变原数组)

let list = [1, 2, 3];
const res = list.reverse();
 
console.log(res);   // [3, 2, 1]
console.log(list);  // [3, 2, 1](原数组已改变)

sort() - 排序(改变原数组)

排序规则

  • 返回值 > 0b 排在 a 前面
  • 返回值 < 0a 排在 b 前面
  • 返回值 = 0:位置不变
let list = [3, 1, 2];
 
// 升序
list.sort((a, b) => a - b);
console.log(list);  // [1, 2, 3]
 
// 降序
list.sort((a, b) => b - a);
console.log(list);  // [3, 2, 1]
 
// 对象数组排序
const users = [
  { name: "张三", age: 18 },
  { name: "李四", age: 20 }
];
users.sort((a, b) => a.age - b.age);

1.6 添加与删除

push() / pop() - 尾部操作(改变原数组)

let list = [1, 2, 3];
 
// push:尾部添加,返回新长度
const len = list.push(4);
console.log(len);   // 4
console.log(list);  // [1, 2, 3, 4]
 
// pop:尾部删除,返回删除的元素
const item = list.pop();
console.log(item);  // 4
console.log(list);  // [1, 2, 3]

shift() / unshift() - 头部操作(改变原数组)

let list = [1, 2, 3];
 
// shift:头部删除,返回删除的元素
const item = list.shift();
console.log(item);  // 1
console.log(list);  // [2, 3]
 
// unshift:头部添加,返回新长度
const len = list.unshift(0);
console.log(len);   // 3
console.log(list);  // [0, 2, 3]

1.7 转换与合并

join() - 数组转字符串

const list = [1, 2, 3];
 
list.join("-");    // "1-2-3"
list.join("");     // "123"
 
// 数组求和
const sum = eval(list.join("+"));
console.log(sum);  // 6

toString() - 转字符串

const list = [1, 2, 3];
const str = list.toString();
 
console.log(str);  // "1,2,3"

concat() - 合并数组

const list = [1, 2, 3];
 
const res = list.concat([4, 5]);
console.log(res);   // [1, 2, 3, 4, 5]
console.log(list);  // [1, 2, 3](原数组不变)
 
// 合并多个数组
const res2 = list.concat([4], [5], 6);
console.log(res2);  // [1, 2, 3, 4, 5, 6]

ES6 替代方案 使用 展开运算符 更简洁:

const res = [...list, 4, 5];

二、ES6+ 新增方法

2.1 includes() - 包含检测

const list = [1, 2, 3];
 
list.includes(2);      // true
list.includes("蛙人");  // false
 
// 支持第二个参数(起始位置)
list.includes(1, 1);    // false(从索引1开始查找)

includes vs indexOf

  • includes 返回布尔值,语义更清晰
  • includes 可以检测 NaNindexOf 不能

2.2 find() / findIndex() - 查找元素

find() - 查找元素值

const list = [1, 2, 3];
 
const found = list.find((item) => item > 1);
console.log(found);  // 2(返回第一个满足条件的值)
 
// 查找对象
const users = [
  { id: 1, name: "张三" },
  { id: 2, name: "李四" }
];
const user = users.find((u) => u.id === 2);
console.log(user);  // { id: 2, name: "李四" }

findIndex() - 查找元素索引

const list = [1, 2, 3];
 
const index = list.findIndex((item) => item > 1);
console.log(index);  // 1(返回第一个满足条件的索引)

2.3 flat() / flatMap() - 扁平化

flat() - 拉平嵌套数组

const list = [1, 2, 3, [4, [5]]];
 
// 拉平一层
list.flat();         // [1, 2, 3, 4, [5]]
 
// 拉平两层
list.flat(2);        // [1, 2, 3, 4, 5]
 
// 完全拉平
list.flat(Infinity); // [1, 2, 3, 4, 5]

flatMap() - 映射后扁平化

const list = [1, 2, 3];
 
// 相当于 map + flat(1)
const res = list.flatMap((item) => [item, item * 2]);
console.log(res);  // [1, 2, 2, 4, 3, 6]

2.4 fill() - 填充数组

改变原数组

let list = [1, 2, 3];
 
// 全部填充
list.fill(0);
console.log(list);  // [0, 0, 0]
 
// 指定范围填充
list = [1, 2, 3, 4, 5];
list.fill(0, 1, 3);  // 从索引1到3(不含3)填充0
console.log(list);  // [1, 0, 0, 4, 5]
 
// 创建并填充
const arr = new Array(3).fill(1);
console.log(arr);  // [1, 1, 1]

2.5 Array.from() - 转真数组

// 伪数组转真数组
const divs = document.getElementsByTagName("div");
const arr = Array.from(divs);
console.log(arr instanceof Array);  // true
 
// 类似 map 操作
const list = [1, 2, 3];
const doubled = Array.from(list, (x) => x * 2);
console.log(doubled);  // [2, 4, 6]
 
// 从字符串创建数组
const strArr = Array.from("abc");
console.log(strArr);  // ['a', 'b', 'c']

2.6 Array.of() - 创建数组

Array.of(1);          // [1]
Array.of(1, 2, 3);    // [1, 2, 3]
 
// 与 Array() 的区别
Array(3);            // [empty × 3](创建长度为3的空数组)
Array.of(3);          // [3](创建包含元素3的数组)

三、方法速查表

3.1 改变原数组的方法

方法说明返回值
push()尾部添加新长度
pop()尾部删除删除的元素
shift()头部删除删除的元素
unshift()头部添加新长度
splice()删除/替换删除的元素数组
sort()排序排序后的数组
reverse()反转反转后的数组
fill()填充填充后的数组

3.2 不改变原数组的方法

方法说明返回值
map()映射新数组
filter()过滤新数组
forEach()遍历undefined
reduce()累加累加结果
slice()截取新数组
concat()合并新数组
join()转字符串字符串
indexOf()查找索引索引或 -1
includes()包含检测true/false
find()查找元素元素值或 undefined
findIndex()查找索引索引或 -1
flat()扁平化新数组
every()全部满足true/false
some()部分满足true/false

四、使用建议

最佳实践

  1. 优先使用不改变原数组的方法,避免副作用
  2. 链式调用map().filter().reduce()
  3. 性能考虑:大数据量时,for 循环比 forEach
  4. 类型判断:使用 Array.isArray() 而非 instanceof

相关链接