前端两年面经分享(字节/阿里)

1,490 阅读18分钟

面试的时间: 2021.7 - 8 月;

希望没有暴露什么敏感信息/手动狗头,这里的面经都是当时写的,没太注意,如果有什么问题的话,欢迎评论区指正~

写在开篇

先交代一下自己的个人背景吧,普通二本的科班本科生,前端 2 年,技术栈以 react 为主,上家公司是杭州某不知名互联网电商中厂,目前在杭州的字节跳动搬砖了六个月,已度过试用期,前来分享面经。

为什么要分享?原因有很多,其实最主要的还是回馈社区吧,面试前的准备,刷题,等等,如果没有社区的资料,那下面的一切可能也不会发生了。

因为个人当时找工作只想跳大厂,所以面试只面了阿里和字节,有点随意的样子,并没有刻意去强求,毕竟其实当时的工作也还行,本来计划是先攒点经验,等年后再试试,不过面了段时间之后机缘巧合下就面上了,挺运气的。(面了很多次,换了很多部门,就硬试~)

在职面试通常是约的晚上远程面试,只有蚂蚁的三面是周三晚上 6 点左右的样子去了那边一趟(然后还挂了)。

现在回过头来看之前的这段面试经历,可以发现面试中其实就只问两部分。

  1. 你简历上的内容。所有的问题都会从你的简历延伸开来,所以你写在简历上的每一点,都要胸有成竹才行,否则就是在给自己找麻烦~
  2. 前端的八股文。可能是知识点,可能是算法题。算法部分的话,就目前而言,前端刷刷 easy 和部分 medium 就够了。

阿里篇

因为内推的同学是以前的同事,好兄弟在 TL 面前猛夸,虽然蚂蚁一面感觉不太好,但还是让我混进了二面,又混进了三面,因为自己简历准备不好的原因,导致第三面答得不好,感觉挺对不起他的(所以才强调简历的内容必须要会

蚂蚁一面 1h40m

聊了挺久的

上来先做个自我介绍,然后开始问一堆项目的细节,穿插各种问题(也不问问 css 之类的,不是说一面都先从简单开始的吗)

webpack 的 plugin 了解吗?(tapable,生命周期的钩子,调用对应的插件)

302, 304,强缓存和协商缓存, expire & cache-control:max-age; last-modified & etag

401 unAuthorized

cas 了解吗,讲一下怎么实现三方登录

(利用 cookie 在不同层级的域名下读取的效果,A 网站带着 cas cookie 访问服务器,如果已登录就刷新 cookie,标识登录成功,否则的话就跳转到 cas 页面,让用户重新登录,登录完之后 redirect 回来,然后再刷新一下登录态即可)

ts, tuple,infer,interface 和 type 的区别,怎么给 window 补充参数,怎么给三方库补充参数,skipLibCheck

react hooks 的运行输出,函数式组件执行的闭包陷阱。(每个触发改变的瞬间,变量的状态是固定的。)(支支吾吾只念叨出个闭包,懂怎么用但是解释不太出来,尴尬)

触发更新的时候,react 会重新执行一遍函数式组件,也就是说,每次更新的时候,函数取得变量的状态都是固定的,这就是函数式组件的闭包陷阱。想解决这个问题的话可以再加一个 useRef,利用对象引用的特性去规避这个问题,或者是 useEffect/useCallback 添加依赖监听

csrf 攻击,防范?

lerna 的用途?(项目经验有关)

git rebase 与 git merge 的区别,git revert(可能有关,不过都是工作中比较常用的)

事件机制,event loop,不断变态的题目,问到知识盲区直接懵逼,事件冒泡机制 + event loop,问为什么是这种输出结果

  • MutationObserver 的特性,微任务。
  • 事件冒泡的时候就会直接将任务先塞到宏任务队列里

compose 实现?当时人傻了没想出来,还说了个错误的方向(一开始联想到洋葱模型,想着用 async/await,得知没必要用之后,看到 next 下意识就想到的 generate,然后说 generate 忘记怎么用了,就放弃了),后面想了想,其实主要就是递归,利用函数栈先进后出就可以实现了。主要还是见识的太少了,面的不够。

蚂蚁二面 43m

上来先做个自我介绍,然后开始聊项目

react hooks,好处,坏处

项目相关的问的比较多

上一面没写出来的 compose 来写一下(递归,利用函数栈先进后出的特性)

nim 游戏,答完之后发现对算法比较了解(其实是发现做过这题),又来了一道走地下城,回答 BFS + 记忆化搜索还不够,又补了个动归,问动归怎么实现,混沌了片刻,给出不太确定的答案最终混了过去。还问了一下 bfs 和动归的复杂度,回答 bfs 应该是 n^2, 加上记忆化搜索应该是 nlogn,这里的 log 几有点忘了,动归和做了记忆化搜索的 bfs 复杂度应该是一样的(大概)

蚂蚁三面 1h

首先是自我介绍,提了项目,介绍了业务的和技术的,主要以业务为主,探讨了很久的业务细节(这里坑了,没解释清楚)

你觉得最有挑战的项目是什么?

hooks 在你们业务中是怎么去使用的?

场景题,如果做技术改造三个月,你会做哪些内容?

然后是你为什么想加入这里?原来的工作对你来说有什么不好的地方?这里也可能踩雷了,以后就回答进入大厂是我一直以来的希望,有机会的话我就会选择加入,原来的公司很好,但是我就是想进入大厂。

后面惯例环节,你有什么问题,让我问了很多工作方面的问题,确认没了之后就结束了整场的面试。

一小时后接到内推同学的反馈,挂了。

果然大佬就是喜欢在你自以为是的时候给你残酷的一击,以后还是放平心态吧,浮躁的人不配当 p6,回答问题的话术方面还要再组织一下,这个自我介绍太长了,举的例子也不够有说服力,卡壳的样子像是不了解这个业务一样,需要重新再打磨一下。

阿里 mmc 一面 25m

这个面试感觉不太一样,上来就开始聊天,聊了聊项目经验,日常工作之类的,以及为什么会想离职,比较放松,具体的八股文只问了一些 react 相关的原理,比如为什么会用 react,而不是 jquery(我的回答是,数据驱动视图,而不是手动修改 dom 节点来处理渲染,摒弃无关操作,聚焦于业务 当然只是个人浅见,仅供参考),然后是 virtual dom 具体是怎么样的,当然自己也展开讲了一些细节,比如说双缓冲机制的 fiber tree,然后 diff 算法的一些细节,从树的最小编辑距离到为了性能提出的优化规则,搬就完事了。然后 25 分钟就解决了战斗,感觉是比较另类的面试体验,可能是跟缺人有关吧,门槛放低了,小白狂喜。

关于离职的理由建议大家最好好好想想,要能说服自己的那种,不然面试的时候被问到会比较蒙圈,卡在那里会显得准备不够。比如说自己也比较想进大厂;平时工作觉得没什么挑战,自己还年轻想来锻炼一下;人事变动比较大觉得是时候出来试试水;或者是出来面试锻炼自己,有机会就进没机会就回去继续上班之类的。/狗头

阿里 mmc 二面 29min

自我介绍

然后纯介绍项目,聊细节,最有难度最有成就感的是什么。

为什么想离职

继续问项目的细节

你想问我什么?(工作的地点;对我有什么建议:技术上听下来都是比较小的点,需要多见见世面 大概是这样……)

纯面项目,这二面感觉有点怪,纯问项目应该是三面才对吧。。整体流程感觉比较干涩,体验上不是很好,纯靠自己讲,感觉干巴巴的(当然确实是两年经历比较少,业务上也没什么特别牛逼的东西,吹不动)

然后原先约的晚上 8 点,结果迟了近 40 分钟才打电话过来,B 站刚看的起劲,感觉自身状态也不是很好,罢了,看运气吧。

(然后果然挂了。

字节篇

飞书一面 50min

不废话,讲完有什么需要补充的之后,直接进入面试主题。

(直接补充:对 react 的细节有一定的了解)

先来道 css 题

大概就是怎么实现一个正方形,在全屏水平垂直居中,宽高都是屏幕宽度的一半(这边只回答了 2 种,宽高就是 50vw,flex 全家桶和绝对定位 50% + transition: transform(50%...)之类的,提一句 css 一般)(还可以 margin + vw,vh 解决)

盒模型(box-sizing: 正常盒模型,怪异盒模型,balabala「我居然还记得住,都没看」)

重绘和回流:是否对其他的元素产生了影响,以此区分是重绘还是回流。然后再讲了一下性能方面,重绘好于回流(好家伙,说的时候好像说反了)

怎么让一个对象的属性不可修改?object.freeze; proxy 修改 set 函数;Object.defineProperty,把对象的 writeable 设置为 false

手写一个事件的订阅发布机制

怎么实现商品选择组件的性能优化机制(面试官是个算法大佬,居然发现了我复述经历里记错的地方,在质疑下我发现了问题并补充了回来 成功混了过去)

react 的 setState 合并,原理,isBatchingUpdate 标志位,再提了一嘴 setTimeout 为什么会不能合并。(然后就举了个例子问我这个是否会合并,差点被反杀)

async onclick = () => {
  this.setState({ a: 1 });
  await sleep(1000);
  this.setState({ a: 2 });
}

业务组件上的难点 -> virtual list -> 实现原理(成功把自己带到了沟里,onScroll 处理当前渲染的数量,但是没讲出滚动条是怎么实现的,再加一个 div,滚动事件绑在新的 div 上就好,height 动态改变)

模拟实现一个 Symbol(这里用 randomString 去模拟实现两个不等,但实际上是犯蠢了,直接 id 累计++就完事了,还可以直接利用 object 的指针不同的特性去实现不等于的条件,相比之下性能好多了。然后不能 new 是可以直接利用箭头函数无法 new 去实现)

虽然说又不是不能用,但是其实还是面试经验不够丰富,导致临场发挥不够,还是要加强自己啊

// 利用箭头函数无法被 new 的特性
const MySymbol = (name) => {
	return {};
}

const aMap = new Map();
MySymbol.for = (name) => {
  let cur = aMap.get(name);
  if (!cur) {
    cur = {};
    aMap.set(name, cur);
  }

  return cur;
}

有什么想问的 > 个人对外面不是很了解,想问问职业规划,过来人的经验分享?

从技术和业务上落地

平时可以多关注一些业务的新动态,看有哪些新的技术可以落地到业务中,反哺业务

看业务中有哪些痛点,难点,可以用技术去解决

follow 大佬们的动态,关注他们学过的。

及时总结。

飞书二面 1h

一些简历上的项目细节

react hooks 好处,对比 class component 的 mixin,还有其他复用逻辑的方法吗?render-props,HOC 都讲一下是怎么实现的

渲染的时候为什么会有 virtual dom(因为直接操作真实的 dom tree 成本高)(感觉还可以再展开来讲讲的,还是太耿直了 直接一句话把问题讲没了,应该再拉着讲一圈 fiber,双缓冲的)

对状态管理了解吗(老久没用 redux 了,现在只会用,一般个人都 hooks + context,就混过去了)

自实现 react-router 怎么做,history 的两种模式(browser、hash)

原型,实现继承,写一个 inherit 函数(Object.setPrototypeOf)

闭包,作用(函数返回函数,跟作用域链有关,也是类似链表;私有变量,模块化的 iife,然后开始讲模块化)

AMD,CMD,区别,为什么有这种区别(node 层 io 性能好,所以同步就够了,浏览器因为是异步加载文件,所以 amd 会比较适合)

事件循环的理解

算法:

  1. 给定一个非负整数 c ,你要判断是否存在两个整数  a  和  b,使得  a^2 + b^2 = c  (先暴力,然后双指针)

  2. 一个整数数组 nums,  需要计算从第 i 个元素到第 j 个元素的和。(一维前缀和)

  3. 给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为  (row1, col1) ,右下角为  (row2, col2) (二维前缀和) 卡住了,面试脑子比较糊 没想出来 结束没多久就懂了 干

时间太紧连保留环节都没了,没有问“你有什么想问我的” ..

挂了,飞书看来还是太侧重刷题了,后面来了个抖音电商的面试,约了下周三。结合邮件的要求其实可以看到,飞书对于偏业务的小伙伴们还是不太友好的,想进飞书的话还是多刷题 8 :<

抖音电商 一面 50min

先是自我介绍

问了点项目

Map 和 WeakMap 的区别 // 好家伙,好像说错了,不过似乎不太影响面试结果,早知道就说不知道了,干

原型链相关的内容,显式和隐式 prototype

var F = funciton() {}
Object.prototype.a = 1;
Function.prototype.b = 2;

var f = new F(); // f上会有什么

useEffect 的原理 // 在 react 处理 render 的生命周期的一些钩子函数

dep,对象浅比较

实现一个 deepEffect,可以实现深比较的。 // 涉及到使用 useRef 实现的 usePrevious

react-router 的原理,hashHistory & browserHistory,hash 模式可以通过 window 监听事件的 hashChange 去监听变化,browserHistory 可以通过 html5 提供的原生 history 封装。

考事件机制,来了道更花的,setTimeout + Promise + async/await 混合使用,问输出的顺序。(不清楚 async/await 语法糖的内部细节,描述了一下事件机制的实现,以及微任务队列增加微任务之后还是会继续执行,就过去了)

一道实现 object 转换的函数,{ 'A.B.C': 1, 'A.B.D': 2 } => { A: { B: { C: 1 }}}

你有什么想问我的?技术栈、进去之后做什么、有什么建议、职业规划方面。

抖音电商 二面

项目经验若干

场景题,怎么继续做你的项目

编程题

const t = new Task();
t
.log(1)
.log(2)
.wait(3)
.log(4)
.wait(5)
.log(6)


// todo
 class Task {
  log() {

  }
}

编程题

// es7 import('./xxx') ==> es5
---
// 场景
loadjs('https://www.bytedance.net/pay.js').then(fn => fn.call(this)) // =>> 'done'

// pay.js
function a(){}
function b(){console.log('done')}
function c(){}

// todo
function loadjs(url: string) :Promise<Function> {
  const code = await fetch(url);
  const sRegx =
}

http 资源缓存,强缓存 & 协商缓存

性能优化相关

http 协议,2.0 的首部压缩,二进制分帧,多路复用

react 写一个搜索组件,节流防抖 + 考虑后发先至

字节电商二面的时候发现和面试官的气场严重不合,多的就不展开讲了,都是运气罢了。然后不出意外的挂了。

抖音短视频 一面

自我介绍

问项目细节

问细节 x2

你们登录是怎么做的?-> 需要再了解一下,大概是 session -> 登录态,记录之类的(账号密码校验完成之后把 sessionId 设置在 cookie 上即可,后续接口请求的登录态通过中间件去处理,读取 sid 并挂载到 ctx 上)

开始问题目

问一道 promise 相关的事件循环题,问了一些 node 相关的内容,node 下的循环机制是怎么样的(也是这样的循环,只是多了一些特殊的 api)

react 的 setState 是同步还是异步(好家伙 问道我会的了 这不得给你整两下,嘻嘻 batchingUpdate -> react 18 的 automatic batchingUpdate)

react 的 virtual dom 的 diff 机制(双缓冲,算法优化,O(n^3) -> O(n),同一层级的同一 type,同一 key 才会去复用 fiber 节点)

搜索的优化怎么处理 -> 防抖与先发后至(好家伙,上次的题目,直接开始复用),节流与防抖的区别。先发后至怎么去处理(记一个 id 去比较,或者是用组件库提供的 abort)

算法题:从二叉树的根到叶子节点称为一条路径,路径上每个节点的 value 之和为路径和值,本题要求所有的路径中是否存在一条和值为 N。(递归,迭代)

有什么想问的:建议 - 再去了解了解 node,你们的登录机制是怎么实现的,探索前端的边界。

抖音短视频是做的啥 - 全栈,偏中台部分,hybird 之类的

抖音短视频 二面

自我介绍

细节 x2 - 项目介绍的有点拉胯,背景包袱太重了,语言也没经过精炼,后续需要再注意一下

http/https 区别

cookie domain path 解释一下(其实都是为了处理 cookie 内容隔离,但是 path 一时半会 get 不到点,就当不了解跳过去了)

缓存相关 强缓存 协商缓存

安全相关,xss,csrf

new 一个对象,具体的实现是什么

0.1 + 0.2 !== 0.3,原因?怎么去处理

box-sizing 介绍一下,解答一下两个盒模型的区别

this 指向的题目,虽然规律记得很清楚,然而还是有部分说错了

AOP 了解吗?实现一下 - 早知道说不了解了,实现不出来 干

洗牌算法的实现,random - 0.5 的弊端(伪随机,大数据量下每个数出现的位置,分布不均匀)

用正则格式化金额。因为正则记不太住规则,就改用代码去实现。(还差点翻车了)

// var length = 10;
// function fn() {
//     console.log(this.length)
// };
// var obj = {
//     length: 5,
//     method: function (fn) {
//         fn(); // 10 window.fn();
//         arguments[0](); // arguments[0](),主体是arguments,所以length = 2
//         fn.call(obj, 12); // 5
//     }
// };

// obj.method(fn, 1);

AOP 实现 - 还不是个 wrapper。。

function wrapper(originFn) {
  return function (...args) {
    originFn?.before.call(this, ...args);
    originFn.call(this, ...args);
    originFn?.after.call(this, ...args);
  }
}


function fn () {
   console.log(123);
}

fn.before = () => console.log(1);
fn.after = () => console.log(1);

fn = wrapper(fn);

fn();

你有什么想问我?给我的建议 - 基础还行,使用类库的时候要深挖,了解具体的实现,不要局限在使用上。

抖音短视频 三面 44min

自我介绍 - 尬住了,忘词了,然后被迫进入下一环节

项目细节,工作细节

实现一个抽奖转盘的组件,补上你认为重要的细节

个人的职业规划

有什么想问我的?(抖音短视频是做什么的(主要是搜索方面的内容);对我有什么建议(对自己的职业规划要更加的清晰,而不是被人推着走,未来一年,未来三年的目标要明确))

抖音短视频 hr 面 1h15min

自我介绍之后开始聊天,整体比较放松

为什么选择前端,你是怎么学前端的,自学前端觉得比较困难的点

对工作的期望

成就感的点

一二三面面试官给你的感觉(觉得 1 2 面面试官比较亲切,整体比较放松,三面有点紧张,感觉发挥不是很好[但是 hr 说三面的面试官给的评价还比较好,有点意外])

看到你面试比较曲折,转了三个部门,你有什么感受,事后有复盘吗(简单的讲就是运气与积累,笔者有点属于临场发挥不佳型,只有做好一定的准备,才可以应对的游刃有余,总的来说就是机会到来之前还是需要自身素质硬,否则只会错过)

期望职级与工资

你是怎么看待职级的,对自身的定位,未来的职业计划

对老东家的看法,氛围,团队,为什么选择离职

在上家公司做些什么,介绍一下自己的职责,评价一下自己在团队中的定位,等

业界里你比较崇拜哪些大佬(不搞个人崇拜,欣赏 + 学习榜样,举了卡颂、黄子毅和 ssh 等大佬,其他的一时半会想不起来了,就没多讲,大佬们的文章对个人的职业发展上都挺有帮助的,感恩)

然后聊了一些脉脉上的信息(bagua),建议我少逛脉脉 /狗头

你有什么想问的?公积金,上班时间以及节奏,公司氛围,房补,然后同步了一下后续的节奏,友好结束。

--- 最后发了书面 offer,成功上岸

参考资料

资料很重要,但是更重要的是建立起自己的知识体系,不论是画思维导图还是别的什么,不要只停留在看,而是要尝试用自己的语言去解释一个知识点。

最后

结尾不卖课不拉群也不留微信

如果要进的话就进卡颂大佬的群吧,他的 react 源码解析也挺棒的,俺也在里面水 /狗头

如果有需要转的可以自己转,带上掘金的作者信息 & 来源就行(没的话就当我没说过~)

最后,希望这篇面经可以帮到你。