每年到校招季,我总能在群里或者面试的时候遇到这样的问题:“能手写一个数组扁平化函数吗?”看似小题,其实挺能看出一个人对 JavaScript 的掌握情况。
我自己这几年面试过不少候选人,发现大家的反应大概分两种:
arr.flat(Infinity)
,一脸轻松。其实都正常,区别在于你是“记住了一个 API”,还是“真正理解了怎么把嵌套数组拆开”。
先从最简单的开始。
const arr = [1, [2, [3, 4]], 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 <= 0) return 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)
类似。 校招面试里,这一步如果能写出来,基本面试官已经给你点头了。
有些同学喜欢一行行函数式写法,那也完全可以:
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 是反向的
}
这种方法不用担心递归深度问题,逻辑也比较清晰: 就像你家有一堆套娃,递归是“从外往里拆到底”, 而迭代就是“把套娃全堆一边,慢慢拆,最后再摆正顺序”。
还有人写过这种看似巧妙的:
function flatten(arr) {
while (arr.some(Array.isArray)) {
arr = [].concat(...arr);
}
return arr;
}
原理是每次只展开一层,循环到没有数组为止。 思路挺巧,但效率未必最好,因为 some
每次都要遍历。 在面试里可以当个补充答案,显示你想过不同角度。
总结下来,扁平化写法大概就这几种:
其实面试官更在意的不是“你写了几种”,而是你能不能讲清楚思路。 比如:为什么递归会爆栈?迭代为什么能避免?如果限制深度你怎么改?
我面过不少候选人,答案写得差不多,但能把背后的逻辑说清楚的人,总是更让人放心。
👆 以上就是我对校招同学的一些经验分享。 如果你还在准备秋招,建议这类小题别只背答案,最好能在纸上推演几遍。 写代码就像练拳,不怕动作简单,就怕你打得没劲。
还没有使用过我们刷题网站(https://fe.ecool.fun/)或者前端面试题宝典的同学,如果近期准备或者正在找工作,千万不要错过,题库主打无广告和更新快哦~。
有会员购买、辅导咨询的小伙伴,可以通过下面的二维码,联系我们的小助手。