JavaScript 数组方法与技巧
数组创建、常用方法、遍历、去重、扁平化等操作
问题
掌握 JavaScript 数组的创建方式、常用方法、遍历技巧以及常见操作(去重、扁平化等)。
解答
数组创建
// 字面量
const arr1 = [1, 2, 3];
// 构造函数
const arr2 = new Array(3); // [empty × 3] 稀疏数组
const arr3 = new Array(1, 2, 3); // [1, 2, 3]
// Array.of - 解决 new Array 的歧义
const arr4 = Array.of(3); // [3]
const arr5 = Array.of(1, 2, 3); // [1, 2, 3]
// Array.from - 从类数组或可迭代对象创建
const arr6 = Array.from('abc'); // ['a', 'b', 'c']
const arr7 = Array.from({ length: 3 }, (_, i) => i); // [0, 1, 2]
改变原数组的方法
const arr = [1, 2, 3];
// push/pop - 尾部操作
arr.push(4); // 返回新长度 4,arr: [1, 2, 3, 4]
arr.pop(); // 返回 4,arr: [1, 2, 3]
// unshift/shift - 头部操作
arr.unshift(0); // 返回新长度 4,arr: [0, 1, 2, 3]
arr.shift(); // 返回 0,arr: [1, 2, 3]
// splice - 删除/插入/替换
arr.splice(1, 1); // 删除索引1的元素,返回 [2],arr: [1, 3]
arr.splice(1, 0, 2); // 在索引1插入2,arr: [1, 2, 3]
arr.splice(1, 1, 'a'); // 替换索引1,arr: [1, 'a', 3]
// sort - 排序
[3, 1, 2].sort((a, b) => a - b); // [1, 2, 3] 升序
[3, 1, 2].sort((a, b) => b - a); // [3, 2, 1] 降序
// reverse - 反转
[1, 2, 3].reverse(); // [3, 2, 1]
// fill - 填充
[1, 2, 3].fill(0); // [0, 0, 0]
[1, 2, 3].fill(0, 1, 2); // [1, 0, 3] 填充索引1到2
不改变原数组的方法
const arr = [1, 2, 3];
// concat - 合并
arr.concat([4, 5]); // [1, 2, 3, 4, 5]
// slice - 截取
arr.slice(1); // [2, 3]
arr.slice(1, 2); // [2]
arr.slice(-2); // [2, 3] 负数从末尾算
// join - 转字符串
arr.join('-'); // '1-2-3'
// indexOf/lastIndexOf - 查找索引
arr.indexOf(2); // 1
arr.lastIndexOf(2); // 1
// includes - 是否包含
arr.includes(2); // true
// find/findIndex - 查找元素
arr.find(x => x > 1); // 2
arr.findIndex(x => x > 1); // 1
// flat - 扁平化
[1, [2, [3]]].flat(); // [1, 2, [3]]
[1, [2, [3]]].flat(2); // [1, 2, 3]
[1, [2, [3]]].flat(Infinity); // [1, 2, 3]
遍历方法
const arr = [1, 2, 3];
// forEach - 遍历,无返回值
arr.forEach((item, index) => {
console.log(item, index);
});
// map - 映射,返回新数组
arr.map(x => x * 2); // [2, 4, 6]
// filter - 过滤
arr.filter(x => x > 1); // [2, 3]
// reduce - 累积
arr.reduce((acc, cur) => acc + cur, 0); // 6
// every - 全部满足
arr.every(x => x > 0); // true
// some - 部分满足
arr.some(x => x > 2); // true
数组去重
const arr = [1, 2, 2, 3, 3, 3];
// 方法1: Set
const unique1 = [...new Set(arr)]; // [1, 2, 3]
// 方法2: filter + indexOf
const unique2 = arr.filter((item, index) => arr.indexOf(item) === index);
// 方法3: reduce
const unique3 = arr.reduce((acc, cur) => {
if (!acc.includes(cur)) acc.push(cur);
return acc;
}, []);
// 对象数组去重(按某个属性)
const users = [
{ id: 1, name: 'a' },
{ id: 2, name: 'b' },
{ id: 1, name: 'c' }
];
const uniqueUsers = users.filter((item, index, self) =>
self.findIndex(u => u.id === item.id) === index
);
// [{ id: 1, name: 'a' }, { id: 2, name: 'b' }]
数组扁平化
const arr = [1, [2, [3, [4]]]];
// 方法1: flat
arr.flat(Infinity); // [1, 2, 3, 4]
// 方法2: 递归
function flatten(arr) {
return arr.reduce((acc, cur) => {
return acc.concat(Array.isArray(cur) ? flatten(cur) : cur);
}, []);
}
// 方法3: 栈
function flattenStack(arr) {
const stack = [...arr];
const result = [];
while (stack.length) {
const item = stack.pop();
if (Array.isArray(item)) {
stack.push(...item);
} else {
result.unshift(item);
}
}
return result;
}
类数组转数组
function example() {
// arguments 是类数组
const args1 = Array.from(arguments);
const args2 = [...arguments];
const args3 = Array.prototype.slice.call(arguments);
}
// NodeList 转数组
const divs = document.querySelectorAll('div');
const divArray = [...divs];
判断数组
Array.isArray([1, 2, 3]); // true
Array.isArray('abc'); // false
// 其他方式(不推荐)
[1, 2, 3] instanceof Array; // true,但跨 iframe 会失效
Object.prototype.toString.call([1, 2, 3]) === '[object Array]'; // true
关键点
- 改变原数组:push/pop/shift/unshift/splice/sort/reverse/fill
- 不改变原数组:concat/slice/map/filter/reduce/flat
- 去重首选
[...new Set(arr)],对象数组用 filter + findIndex - 扁平化首选
arr.flat(Infinity),兼容性要求高用递归 - 判断数组用
Array.isArray(),最可靠
目录