JavaScript数组降维之将二维数组转为一维数组的五种方案

 更新时间:2026年05月08日 09:30:05   作者:yqcoder  
本文介绍了五种数组降维方法,从最简单的Array.prototype.flat()方法,到兼容旧版本的concat;spread方法,再到通用的reduce方法,以及处理任意深度嵌套的递归方法, 兌时建议总结不同方法的特点、适用场景和性能差异,需要的朋友可以参考下

在处理数据时,我们经常会遇到这样的结构:

const arr = [
  [1, 2],
  [3, 4],
  [5, 6],
];

我们希望把它变成:

[1, 2, 3, 4, 5, 6];

这个过程被称为 “数组扁平化” (Array Flattening)

很多开发者知道 flat(),但你知道它有哪些替代方案吗?在兼容性要求高的老项目中该怎么办?如果数组层级不确定又该如何处理?

本文将带你掌握 5 种 主流方法,从最简单到最底层,彻底搞定数组降维。

1. 首选方案:Array.prototype.flat()

这是 ES2019 (ES10) 引入的最简单、最直观的方法。

基本用法

flat() 方法会创建一个新数组,其中所有子数组元素以递归方式连接到指定深度。

const arr = [
  [1, 2],
  [3, 4],
  [5, 6],
];

// 默认只扁平化一层
const result = arr.flat();
console.log(result); // [1, 2, 3, 4, 5, 6]

控制深度

如果数组嵌套更深,可以传入参数指定深度。

const deepArr = [1, [2, [3, [4]]]];

console.log(deepArr.flat()); // [1, 2, [3, [4]]]       (默认深度 1)
console.log(deepArr.flat(2)); // [1, 2, 3, [4]]         (深度 2)
console.log(deepArr.flat(Infinity)); // [1, 2, 3, 4]      (无限深度,完全扁平)

优点

  • 语法极简,语义清晰。
  • 支持自定义深度。
  • 自动跳过空位(sparse arrays)。

注意

  • 兼容性:IE 不支持。如果需要支持 IE,请使用 Babel 转译或下面的其他方法。

2. 经典方案:concat + spread

flat() 出现之前,这是最常用的“一行代码”解法,适用于仅有一层嵌套的二维数组。

代码实现

利用 Array.prototype.concat() 可以接受多个参数或数组作为参数的特性,结合展开运算符 ...

const arr = [
  [1, 2],
  [3, 4],
  [5, 6],
];

// 方法 A: 使用 apply (旧式写法)
const resultA = [].concat.apply([], arr);

// 方法 B: 使用 Spread 运算符 (推荐,更现代)
const resultB = [].concat(...arr);

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

局限性

  • 只能处理一层嵌套。如果数组是 [[1, [2]], [3]],结果会是 [1, [2], 3],内部的 [2] 不会被展开。
  • 参数长度限制:如果数组非常大(例如超过几万个元素),...arr 可能会导致调用栈溢出(Maximum call stack size exceeded),因为 concat 的参数个数有限制。

3. 通用方案:reduce 累加器

reduce 是数组处理的神器,它可以灵活地构建任何结构。对于二维数组,我们可以用 reduce 配合 concat 来实现。

代码实现

const arr = [
  [1, 2],
  [3, 4],
  [5, 6],
];

const result = arr.reduce((acc, cur) => {
  return acc.concat(cur);
}, []);

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

进阶:配合 Spread

const result = arr.reduce((acc, cur) => [...acc, ...cur], []);

注意[...acc, ...cur] 每次都会创建新数组,性能比 acc.concat(cur) 差,建议优先使用 concat

与 flat() 对比

  • reduce 方案同样默认只处理一层
  • 优点是兼容性极好(ES5 即可支持)。
  • 缺点是代码稍长,不如 flat() 直观。

4. 递归方案:处理任意深度嵌套

如果数据层级不确定(可能是三维、四维甚至更深),或者你需要兼容旧环境且不能使用 flat(Infinity),则需要使用递归

代码实现

function flattenDeep(arr) {
  let result = [];

  arr.forEach((item) => {
    if (Array.isArray(item)) {
      // 如果是数组,递归调用
      result = result.concat(flattenDeep(item));
    } else {
      // 如果不是数组,直接加入
      result.push(item);
    }
  });

  return result;
}

// 测试
const deepArr = [1, [2, [3, [4, 5]]], 6];
console.log(flattenDeep(deepArr)); // [1, 2, 3, 4, 5, 6]

优化版:使用 reduce + 递归

function flattenDeep(arr) {
  return arr.reduce((acc, val) => {
    return acc.concat(Array.isArray(val) ? flattenDeep(val) : val);
  }, []);
}

优点

  • 兼容所有环境。
  • 逻辑清晰,易于理解。

注意

  • 递归过深可能导致栈溢出。对于极深层级的数据,建议使用**栈(Stack)**实现的迭代方式。

5. 选型指南与性能对比

方法适用场景兼容性性能推荐指数
flat()现代项目首选,代码简洁ES2019+ (需 Polyfill for IE)⭐⭐⭐⭐🌟🌟🌟🌟🌟
concat(...arr)确定只有一层嵌套,且数据量不大ES6+⭐⭐⭐🌟🌟🌟
reduce + concat需要兼容旧浏览器,且只有一层嵌套ES5+⭐⭐⭐⭐🌟🌟🌟🌟
递归/迭代层级不确定,或需自定义过滤逻辑所有环境⭐⭐ (递归有开销)🌟🌟🌟

最佳实践建议

  1. 日常开发:直接使用 arr.flat()。如果需要考虑 IE,引入 core-js 等 Polyfill 库即可。
  2. 高性能要求:如果数组非常大(百万级),避免使用 reduce 配合展开运算符 [...acc, ...item],因为它会频繁创建新数组。推荐使用 flat() 或传统的 for 循环 + push
  3. 复杂逻辑:如果在扁平化的同时需要过滤数据或转换格式,reduce 是最灵活的选择。
// 示例:扁平化并只保留偶数
const arr = [
  [1, 2],
  [3, 4],
  [5, 6],
];
const evenNumbers = arr.flat().filter((n) => n % 2 === 0);
// [2, 4, 6]

总结

  • 最简单arr.flat()
  • 最兼容(单层)[].concat(...arr)
  • 最灵活(多层/自定义):递归函数或 reduce

掌握这些方法,你就能从容应对任何数组嵌套场景。记住,工具没有好坏,只有适不适合。在现代 Vue/React 项目中,请放心拥抱 flat()

以上就是JavaScript数组降维之将二维数组转为一维数组的五种方案的详细内容,更多关于JavaScript二维数组转为一维数组的资料请关注脚本之家其它相关文章!

相关文章

  • 原生javascript实现的全屏滚动功能示例

    原生javascript实现的全屏滚动功能示例

    这篇文章主要介绍了原生javascript实现的全屏滚动功能,涉及javascript事件响应及页面元素属性动态操作相关实现技巧,需要的朋友可以参考下
    2017-09-09
  • JS获取当前网页大小以及屏幕分辨率等

    JS获取当前网页大小以及屏幕分辨率等

    这篇文章主要介绍了JS获取当前网页大小以及屏幕分辨率等,方法虽简单,但比较实用,需要的朋友可以参考下
    2014-09-09
  • JavaScript获取页面上某个元素的代码

    JavaScript获取页面上某个元素的代码

    大多数的javascript操作都需要获取先获取页面上的某个元素,引用其为当前脚本中的一个对象,然后加以操作或获取节点树形。
    2011-03-03
  • xmlHTTP实例

    xmlHTTP实例

    xmlHTTP实例...
    2006-10-10
  • JS中常见的8种继承方法总结

    JS中常见的8种继承方法总结

    这篇文章主要给大家介绍了关于JS中常见的8种继承方法,在js中所有的引用类型都继承了Object,而继承也是通过原型链实现的,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-10-10
  • 微信小程序转换uniapp的迁移步骤以及遇到的问题总结

    微信小程序转换uniapp的迁移步骤以及遇到的问题总结

    最近公司有个需求,第一次遇到,把原生的微信小程序代码转换为uni-app项目,下面这篇文章主要给大家介绍了关于微信小程序转换uniapp的迁移步骤以及遇到问题的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • JS获取鼠标位置距浏览器窗口距离的方法示例

    JS获取鼠标位置距浏览器窗口距离的方法示例

    这篇文章主要介绍了JS获取鼠标位置距浏览器窗口距离的方法,结合实例形式分析了JS针对各种常见浏览器窗口及鼠标响应操作相关技巧,需要的朋友可以参考下
    2017-04-04
  • JavaScript仿京东放大镜特效

    JavaScript仿京东放大镜特效

    这篇文章主要为大家详细介绍了JavaScript仿京东放大镜特效,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • JavaScript实现向setTimeout执行代码传递参数的方法

    JavaScript实现向setTimeout执行代码传递参数的方法

    这篇文章主要介绍了JavaScript实现向setTimeout执行代码传递参数的方法,分析了向setTimeout传递参数的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-04-04
  • 前端实现打印功能的两种方法详解

    前端实现打印功能的两种方法详解

    当页面设计好后需要打印出来,如网页的的打印浏览和打印功能,有些公司需要让前端开发好页面打印出来或者转为pdf格式的文档,下面这篇文章主要给大家介绍了关于前端实现打印功能的两种方法,需要的朋友可以参考下
    2023-01-01

最新评论