JavaScript 数组高阶技巧:10 个实用方法从入门到进阶

更新日期: 2026-03-25 阅读: 27 标签: 数组

数组是 JavaScript 中最常用的数据结构之一。除了基础的 push、pop、map、filter,还有很多高级技巧可以让代码更优雅、更高效。本文整理了 10 个实用数组操作,涵盖去重、扁平化、分组、树形转换等常见场景。


1. 数组去重的 3 种写法

初级写法

function unique(arr) {
  const res = [];
  for (let i = 0; i < arr.length; i++) {
    if (res.indexOf(arr[i]) === -1) {
      res.push(arr[i]);
    }
  }
  return res;
}

中级写法

function unique(arr) {
  return [...new Set(arr)];
}

高级写法(对象数组去重)

function uniqueBy(arr, key) {
  return [...new Map(arr.map(item => [item[key], item])).values()];
}

const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 1, name: 'Alice' } // 重复
];

console.log(uniqueBy(users, 'id'));
// [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]

原理:Map 会保留相同键的最后一个值,配合 .values() 即可完成对象数组去重。


2. 扁平化数组有多简单

多层嵌套数组扁平化,一行代码即可搞定:

const nested = [1, [2, [3, [4, 5]]]];

// ES2019+ 直接用 flat()
console.log(nested.flat(Infinity)); // [1, 2, 3, 4, 5]

// 兼容旧浏览器的写法
console.log(JSON.parse(`[${nested}]`)); // [1, 2, 3, 4, 5]

JSON 序列化方式将 [1,[2,[3]]] 转为字符串再转回数组,实现自动扁平化。


3. 数组分块的优雅写法

将大数组分成固定大小的块:

function chunk(arr, size) {
  return Array.from(
    { length: Math.ceil(arr.length / size) },
    (_, i) => arr.slice(i * size, (i + 1) * size)
  );
}

console.log(chunk([1, 2, 3, 4, 5, 6], 2));
// [[1, 2], [3, 4], [5, 6]]

Array.from 的第二个参数是映射函数,可同时进行索引计算和切片,比传统 for 循环简洁许多。


4. 快速判断数组包含指定项

简单值判断用 includes,对象数组判断用 some 或 every:

const arr = [1, 2, 3, 4, 5];
console.log(arr.includes(3)); // true

const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];
console.log(users.some(u => u.id === 2)); // true
console.log(users.every(u => u.id > 0)); // true
  • some:任意一个满足条件返回 true

  • every:所有项都满足条件返回 true

  • 比 find + undefined 判断语义更清晰


5. 数组映射转对象超方便

将数组转为键值对对象:

const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Charlie' }
];

const userMap = Object.fromEntries(users.map(u => [u.id, u]));
console.log(userMap);
// {
//   1: { id: 1, name: 'Alice' },
//   2: { id: 2, name: 'Bob' },
//   3: { id: 3, name: 'Charlie' }
// }

console.log(userMap[2]); // { id: 2, name: 'Bob' }

Object.fromEntries 是 ES2019 新增的方法,与 Object.entries 互为逆操作,是数组转对象的神器。


6. 数组乱序算法(Fisher-Yates 洗牌)

function shuffle(arr) {
  const res = [...arr];
  for (let i = res.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [res[i], res[j]] = [res[j], res[i]];
  }
  return res;
}

console.log(shuffle([1, 2, 3, 4, 5]));
// 随机顺序:[3, 1, 5, 2, 4]

解构赋值 [a, b] = [b, a] 交换元素,比传统临时变量方式更优雅。


7. 数组取交集和差集

const arr1 = [1, 2, 3, 4, 5];
const arr2 = [3, 4, 5, 6, 7];

// 交集
const intersection = [...new Set(arr1)].filter(x => arr2.includes(x));
console.log(intersection); // [3, 4, 5]

// 差集(arr1 有但 arr2 没有)
const difference = [...new Set(arr1)].filter(x => !arr2.includes(x));
console.log(difference); // [1, 2]

// 并集
const union = [...new Set([...arr1, ...arr2])];
console.log(union); // [1, 2, 3, 4, 5, 6, 7]

核心思路:先用 Set 去重,再用 filter 筛选,配合 includes 判断是否存在。


8. 数组最大/最小值

const numbers = [12, 45, 7, 89, 32];

console.log(Math.max(...numbers)); // 89
console.log(Math.min(...numbers)); // 7

// 超大数组避免堆栈溢出
function getMax(arr) {
  return arr.reduce((max, num) => num > max ? num : max, -Infinity);
}

const bigArray = new Array(100000).fill(0).map((_, i) => i);
console.log(getMax(bigArray)); // 99999

注意:Math.max(...arr) 会展开数组,超大数组可能导致堆栈溢出,此时用 reduce 更安全。


9. 数组分组(GroupBy)

ES2024 已原生支持 Object.groupBy,在此之前可以手动实现:

const users = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
  { name: 'Charlie', age: 25 },
  { name: 'David', age: 30 }
];

// 手动实现
const groupBy = (arr, key) =>
  arr.reduce((acc, item) => {
    (acc[item[key]] ??= []).push(item);
    return acc;
  }, {});

console.log(groupBy(users, 'age'));
// {
//   25: [{ name: 'Alice', age: 25 }, { name: 'Charlie', age: 25 }],
//   30: [{ name: 'Bob', age: 30 }, { name: 'David', age: 30 }]
// }

// ES2024 原生写法
const grouped = Object.groupBy(users, ({ age }) => age);

??= 空值赋值运算符:只有当值为 null 或 undefined 时才赋值,比 ||= 更严谨。


10. 数组转树形结构

后端返回扁平数组,前端转成树形结构:

const list = [
  { id: 1, pid: 0, name: 'A' },
  { id: 2, pid: 1, name: 'A-1' },
  { id: 3, pid: 1, name: 'A-2' },
  { id: 4, pid: 2, name: 'A-1-1' },
  { id: 5, pid: 0, name: 'B' }
];

function buildTree(arr, pid = 0) {
  return arr
    .filter(item => item.pid === pid)
    .map(item => ({
      ...item,
      children: buildTree(arr, item.id)
    }));
}

console.log(buildTree(list));
// [
//   { id: 1, pid: 0, name: 'A', children: [
//     { id: 2, pid: 1, name: 'A-1', children: [
//       { id: 4, pid: 2, name: 'A-1-1', children: [] }
//     ]},
//     { id: 3, pid: 1, name: 'A-2', children: [] }
//   ]},
//   { id: 5, pid: 0, name: 'B', children: [] }
// ]

递归加双重过滤:先筛选当前层级的节点,再递归构建子节点,经典而优雅的实现方式。


总结

这些数组技巧看似简单,但组合起来可以解决很多实际问题:

  • 去重、分组、树形转换是数据处理的核心

  • Set、Map、Object.fromEntries 是现代 JavaScript 的神器

  • 解构赋值、空值赋值让代码更简洁

用好数组,代码质量会提升一个台阶。

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://fly63.com/article/detial/13510

相关推荐

indexOf的三种使用方法

indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。这里基本用法大家一般都清楚,一般在实际工作中常与数组的方法合用来对数组进行一些操作

关于Vue不能监听(watch)数组变化

vue无法监听数组变化的情况,但是数组在下面两种情况下无法监听:利用索引直接设置数组项时,例如arr[indexofitem]=newValue;修改数组的长度时,例如arr.length=newLength

JS计算两个数组的交集、差集、并集、补集(多种实现方式)

使用 ES5 语法来实现虽然会麻烦些,但兼容性最好,不用考虑浏览器 JavaScript 版本,使用 ES5 语法来实现虽然会麻烦些,但兼容性最好,不用考虑浏览器 JavaScript 版本。也不用引入其他第三方库。

js数组中改变元素的位置:互换,置顶,上移,下移

unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。splice() 方法可删除从 index 处开始的零个或多个元素

js使用数组+循环+条件实现数字转换为汉字的简单方法。

单个数字转汉字的解决方法:利用数组存储0-9的汉字、 ary.length和str.length不用多说,这是指ary数组和str字符串的长度。这里我们需要注意的是str.charAt(j)和ary[i],分别指在str这个字符串中索引为j的元素,在ary中索引为i的元素。

Js遍历数组时注意 Empty Item 的影响

这两天碰到个问题:从日志中发现一些来自 iOS 10.3 的报错「Cannot read property \\\'xxx\\\' of undefined」,定位到代码的报错位置,发现是遍历某数组时产生的报错,该数组的元素应该全都是 Object,但实际上出现了异常的元素

JS数组扁平化(flat)方法总结

需求:多维数组=>一维数组 ;flat和flatMap方法为ES2019(ES10)方法,目前还未在所有浏览器完全兼容。第四种处理:用 reduce 实现数组的 flat 方法

数组、字符串去重

今天说的数组和字符串去重呢,主要用到es6新的数据结构 Set,它类似于数组,但是成员的值都是唯一的,没有重复的值,所以活用Set来进行数组和字符串的去重。

Js数组中所有方法(超详细)

concat()把元素衔接到数组中。 every() 方法使用指定函数检测数组中的所有元素:filter()返回满足断言函数的数组元素。forEach()为数组的每一个元素调用指定函数。

[译]async-await 数组循环的几个坑

在 Javascript 循环中使用 async/ await 循环遍历数组似乎很简单,但是在将两者结合使用时需要注意一些非直观的行为。让我们看看三个不同的例子,看看你应该注意什么,以及哪个循环最适合特定用例。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!