面试官最爱问的数组扁平化,你能写几种?

每年到校招季,我总能在群里或者面试的时候遇到这样的问题:“能手写一个数组扁平化函数吗?”看似小题,其实挺能看出一个人对 JavaScript 的掌握情况。

我自己这几年面试过不少候选人,发现大家的反应大概分两种:

  • 有人脱口而出 arr.flat(Infinity),一脸轻松。
  • 也有人愣住半天,开始在草稿纸上画方括号。

其实都正常,区别在于你是“记住了一个 API”,还是“真正理解了怎么把嵌套数组拆开”。


一行写法:flat

先从最简单的开始。

const arr = [1, [2, [34]], 5];
arr.flat(Infinity); // [1, 2, 3, 4, 5]

ES2019 加了 flat() 方法,默认扁平一层,加个参数可以控制深度。【日常开发】里用这个就完事了,没必要造轮子。 但在面试里,如果你只写这一句,面试官多半会笑着说: “那能自己写一个吗?”

意思是:API 你知道挺好,但我更想看你脑子里有没有底层思路。


最经典的:递归

大部分候选人写到这里就能给出答案了:

function flatten(arr{
  let res = [];
  for (let item of arr) {
    if (Array.isArray(item)) {
      res = res.concat(flatten(item)); // 递归展开
    } else {
      res.push(item);
    }
  }
  return res;
}

原理其实很朴素:遇到数组就继续拆,遇到值就收集起来。 这种写法能处理任意层级,面试官也会觉得思路清晰。

不过经常会追问一句:“如果我只想扁平两层呢?” 那就给函数加个参数:

function flatten(arr, depth = 1{
if (depth <= 0return arr.slice();
let res = [];
for (let item of arr) {
    if (Array.isArray(item)) {
      res = res.concat(flatten(item, depth - 1));
    } else {
      res.push(item);
    }
  }
return res;
}

这里面其实就跟自己实现了一个 flat(depth) 类似。 校招面试里,这一步如果能写出来,基本面试官已经给你点头了。


换个角度:reduce

有些同学喜欢一行行函数式写法,那也完全可以:

const flatten = arr =>
  arr.reduce((acc, cur) => 
    acc.concat(Array.isArray(cur) ? flatten(cur) : cur), []);

本质还是递归,只是把循环换成了 reduce,更“函数式”一点。 这一版可读性见仁见智,但能展示你熟悉高阶函数。


避免爆栈:用迭代代替递归

有一次我面过一个同学,我故意问他:“如果数组嵌套一万层,你的递归还能跑吗?” 他愣了几秒说:“会爆栈吧?” 我笑着点头。

是的,递归写法虽然直观,但层级太深就可能报错。 这个时候可以手写一个迭代版本,用显式栈来模拟递归:

function flattenIterative(arr{
const stack = [...arr]; // 初始堆栈
const res = [];
while (stack.length) {
    const item = stack.pop();
    if (Array.isArray(item)) {
      stack.push(...item); // 展开再放回栈
    } else {
      res.push(item);
    }
  }
return res.reverse(); // 因为 pop 是反向的
}

这种方法不用担心递归深度问题,逻辑也比较清晰: 就像你家有一堆套娃,递归是“从外往里拆到底”, 而迭代就是“把套娃全堆一边,慢慢拆,最后再摆正顺序”。


奇技淫巧:while + some

还有人写过这种看似巧妙的:

function flatten(arr{
  while (arr.some(Array.isArray)) {
    arr = [].concat(...arr);
  }
  return arr;
}

原理是每次只展开一层,循环到没有数组为止。 思路挺巧,但效率未必最好,因为 some 每次都要遍历。 在面试里可以当个补充答案,显示你想过不同角度。


面试里真正想看的是什么?

总结下来,扁平化写法大概就这几种:

  • **flat()**:直接用 API(展示知道语法糖)
  • 递归:最直观,面试官最想看的基本功
  • reduce:函数式变体
  • 迭代 + 栈:展示对爆栈问题有思考
  • while + some:小 trick,可以锦上添花

其实面试官更在意的不是“你写了几种”,而是你能不能讲清楚思路。 比如:为什么递归会爆栈?迭代为什么能避免?如果限制深度你怎么改?

我面过不少候选人,答案写得差不多,但能把背后的逻辑说清楚的人,总是更让人放心。


👆 以上就是我对校招同学的一些经验分享。 如果你还在准备秋招,建议这类小题别只背答案,最好能在纸上推演几遍。 写代码就像练拳,不怕动作简单,就怕你打得没劲。

最后

还没有使用过我们刷题网站(https://fe.ecool.fun/)或者前端面试题宝典的同学,如果近期准备或者正在找工作,千万不要错过,题库主打无广告和更新快哦~。

有会员购买、辅导咨询的小伙伴,可以通过下面的二维码,联系我们的小助手。

Image