前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库concat 与展开运算符嵌套数组
JSJavaScript数组与集合

concat 与数组展开怎样合并数组,为什么嵌套和空位结果不同?

两个写法对普通密集数组常常相似,但它们决定“展开什么”的规则并不一样。

前端进阶之旅 · 一题精讲更新于 2026.09.06
JavaScript#数组与集合#容器化
先看核心答案读代码示例
理解线索

比较三个层次的结果

  1. 外层数组两种常见合并写法都会新建容器
  2. 内层引用嵌套值不会自动递归克隆
  3. 读取协议concat 展开标记与 iterator 分别控制行为

“展开一层”描述普通参数数组的合并效果,不代表 concat 会读取任意对象内部的数组字段或自动递归处理所有嵌套。

核心回答

先记住这个答案

对普通数组,concat 与 [...a, ...b] 都能构造一个浅合并的新数组,不会递归拆开任意嵌套层级,内层对象和数组仍共享引用。concat 按自己的可展开规则处理参数,普通数组默认展开一层,并可受 Symbol.isConcatSpreadable 影响;数组展开则消费 Symbol.iterator。普通稀疏数组经 concat 可保留空位,经数组展开通常变成显式 undefined。因此不能把二者说成对所有输入完全等价。若需要深度展平,应明确使用 flat 的深度及其空位规则。

  • 新外层容器仍共享嵌套对象与数组
  • concat 与 spread 使用不同展开契约
  • 稀疏结构是观察差异的直接用例

先确认合并后哪一层仍然共享

示例将一个包含内层数组的容器与另一数组合并,两种写法都保留同一个内层数组引用。后续修改内层时,两份结果都能看到变化,说明浅合并不是数据隔离操作。

第二组使用只有长度的稀疏数组,结果值打印可能相似,因此通过 Object.hasOwn 检查自有索引。这个断言比只看 JSON 更准确,因为 JSON 会把空位和 undefined 都编码成 null。

嵌套引用与空位分别比较JavaScript
const nested = [1, 2];
const left = [nested];
const joined = left.concat([3]);
const spread = [...left, 3];
console.log(joined[0] === nested, spread[0] === nested);
nested.push(4);
console.log(JSON.stringify(joined));
const sparse = new Array(1);
console.log(Object.hasOwn([].concat(sparse), 0));
console.log(Object.hasOwn([...sparse], 0));
查看输出与解释
true true
[[1,2,4],3]
false
true

内层数组没有被克隆,增加四后合并结果同步看到变化。concat 保留缺失索引,而普通数组迭代器展开后写入显式 undefined,所以自有属性检查结果不同。

参数不是真数组时要看实际协议

Set 可以通过数组展开产生成员,但把 Set 直接传给 concat 通常只是追加这个对象本身。另一方面,一个带 length 和索引的对象可以用 Symbol.isConcatSpreadable 表达 concat 展开意图,却不因此自动拥有迭代器。

接口设计最好选定清晰输入类型,避免同时支持很多隐式展开约定。若接收外部集合,先按受控转换规则标准化,再合并,错误提示也更容易指向真正不符合约定的输入。

展平深度与复制深度是两件事

flat 可以按指定层数去掉数组嵌套,但结果中的对象依然是引用,并不等于深拷贝。需要把树形记录转成列表时,还应明确哪些层级代表结构、哪些数组本身是合法业务值。

大数据合并会分配新容器,反复在循环里 concat 不断增长的数组可能重复复制已有内容。应根据吞吐和内存证据选择一次构造或受控累积,不能只追求一行写法而忽略总分配。

回答前,多想一步

容易答错的地方

把 concat 和 spread 说成完全相同的语法糖
两者对迭代器、展开标记和空位的处理不同,普通密集数组结果相同只是常见子集。替换时应检查输入契约和属性结构,尤其是自定义集合与稀疏数组。
认为新数组里的嵌套数据都已复制
浅合并只建立外层容器,内层引用仍可共享。若后续要修改嵌套内容,应复制必要层级或采用明确不可变更新,避免修改合并结果时意外改变输入。
试着用自己的话回答

面试官还会怎么问?

concat 会修改调用它的原数组吗?

普通数组 concat 返回新数组而不主动修改源容器,但读取访问器或自定义对象仍可能产生用户定义副作用。常规业务可按非修改合并理解,同时不要把它扩张为对任意对象绝无副作用。

为什么 Set 用 concat 没有展开成员?

concat 不按 Set 的默认迭代器收集成员,通常把它当作普通单项参数。需要成员列表时应显式展开或 Array.from 转换,让代码表达清楚想追加集合本身还是集合里的每个值。

要合并很多小数组怎样减少重复复制?

可以一次收集输入后合并,或在受控目标数组里逐项累积,再按需要冻结或发布结果。选择应考虑数据规模与可变约束,避免在每轮都复制越来越长的已有结果。

从一道题,走向一组知识

把知识连起来

数组与集合

copyWithin 怎样在数组内部复制,源目标重叠会覆盖错吗?

对照同一数组内部覆盖与创建新数组的合并。

数组与集合

数组展开为什么能复制数组和 Set,它到底读取了什么?

理解 Set 与自定义对象何时能按迭代协议展开。

数组与集合

Array.prototype.flat 的默认展平深度是多少?flatMap 与先 map 再 flat 有何不同?

选择明确展平深度,而不是依赖浅合并猜测嵌套结果。

参考资料

  • MDN:concat
  • MDN:展开语法

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 先确认合并后哪一层仍然共享
  3. 参数不是真数组时要看实际协议
  4. 展平深度与复制深度是两件事
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑