字节幸福里校招前端面经 1面+2面+3面+hr面(已意向)
2021.10.9 更新,收到了字节的意向书 (´▽`ʃ♡ƪ),总结一下秋招大概是有惊无险,博主简历投的太晚了,9月中旬才开始投,有响应的就阿里、腾讯、美团和字节,阿里刚面一轮 hc 就无了,美团因为 ac 率太低死在了笔试,腾讯因为懒没去官网更新简历🤭。还好面字节侥幸过了三轮面试最后拿到了意向书。今天来总结一下这三面的面经,总的来说字节面试就几个方面:
- 计算机科学(计算机网络、操作系统、数据库等),前端这方面主要考的就是计算机网络 http、http2、http3、ssl/tls、tcp/ip、dns、cdn这些考的比较多,操作系统偶尔会问问进程、线程、协程(es6 generator的概念),数据库会顺便问问锁机制啥的。
- 前端基础(H5、C3、ES678910、webApi、浏览器、前端测试、打包工具...)。
- 框架(react、vue二选一)。TS(会ts真的很加分)。
- 编程思维(函数式编程、面向对象编程、设计模式、mixin、原型、、、)
- 算法(leetcode中等到稍微困难难度)。
顺带一提博主本人是个学渣,双非普本苦逼毕业生,主攻web前端和golang,觉得后端太卷就面的前端。在学校搞过几年比赛,大三的时候在百度实习过一阵子。所以由此见得前端这个行业现在还不是很卷,一般不会因为学历卡人,丰富的经历反而比较重要。
技术1面 (1h)
一面隔的太久了,问什么记不清了,但是考察的重点围绕在计算机网络、操作系统这块.源码没怎么问,依稀记得这几道题:
- 横向对比一下 react 和 vue,相同点和异同点。(相同点围绕着数据流和组件化以及diff策略来答,异同点围绕着更新的触发方式,以及异步和同步的渲染过程来答。)
- 全屏局中的正方形。(面试官想让我用 vw/vh,结果我用的 margin-top + 绝对居中,不过后来又解释了 vm 和 vh 的用法以及兼容性问题。)
- 移动端主流布局方案。(说的 flexible + rem,还有其他的几个,主要解释了 rem 的实现原理,就是等比缩放以及 dpi、物理像素、设备像素等概念。)
- https的实现原理。(简单讲了一下 ssl 协议,对称加密、非对称加密、证书、数字签名和ssl握手过程。)
- http2.0、http3.0。(http2 围绕帧协议、服务端推送、并发、首部压缩、协议升级握手过程来讲,http3讲了一下解决了什么问题(头阻塞、TCP协议僵化),然后说了是基于 QUIC 走 UDP流。)
- 一道 promise 题,忘了内容了,不过从三面都考了异步编程这点来看,异步编程属实面试香饽饽,记得多复习一下。
- 算法题,广度优先遍历?(喵喵喵?这不白给。。。)
技术2面 (1h 5min)
二面的面试官有点狠,因为我简历里写了读过 react16.8.0 的完整源码,所以全程都在侃源码:
- hook 的实现原理? (我说 hook 类似细粒度的 fiber,解释了一下几个 api 的主要实现,提了一下 useLayoutEffect 和 useEffect 的执行时机的差异等等,然后重点说了 hook 的意义。)
- react scheduler 调度器如何 polefill requestIdleCallback 这个 api? (这其实就是利用 requestAnimationFrame 这个 api 来维护浏览器每帧的刷新间隔,然后通过 window.postMessage 来安排合适的任务执行时机。)
- fiber 的调度过程?(先通过 scheduler 进行异步调度,然后就俩阶段,render 阶段负责调和子节点构建 fiber 树以及 dom 树构建和一些属性的初始化等等等,整体来看是一个递
perforUnitOfWork
和归completeWork
的过程;commit 阶段不可打断分三部分 before mutation、mutation、layout分别负责不同的任务。) - 合成事件机制?(回答了事件委托以及 react 是如何模拟事件冒泡以及事件捕获的。)
- webpack 的实现原理?(这个我不太熟,答了如何构建效率优化。)
- babel 的实现原理?(答了词法分析、语法分析构建抽象语法树,然后通过访问器模式提供代码替换。)
- vue3.0 reactivity 的实现原理?(额因为我简历挂了一个掘金的博客地址关于 vue3.0 响应式 api 源码解读 地址,就简单考了考,博客还挺加分的。)
- 编程题:由于当前环境下没有本地实现的加法函数,加法是通过异步 api 实现的,一次只支持两个数字参数,要求实现一个加法函数支持多个参数,要求最快的计算效率。(这道题我优化了三个版本,第三个版本是用了一个结果池,找不到了。)
const addRemote = async (a: number, b: number) => new Promise((resolve) => { setTimeout(() => resolve(a + b), 1000); }); // version 1.0 async function add_v1(...inputs: number[]) { let handler = Promise.resolve(inputs[0]); for (let i = 1; i < inputs.length; i++) { handler = handler.then((res) => { return addRemote(res, input[i]).then((res) => { return res; }); }); } await handler.then((res) => { return res; }); } // version 2.0 async function add_v2(...inputs: number[]) { if (inputs.length === 1) { console.log(inputs[0]); return inputs[0]; } let tasks = []; let i = 0; for (; i < inputs.length; i += 2) { tasks.push(addRemote(inputs[i], inputs[i + 1])); } let handler = Promise.all(tasks); let res = await handler.then((res) => { return add_v2(...([...res, ...inputs.slice(i + 1)] as number[])); }); return res; } add_v2(1, 2, 3, 4).then((res) => { console.log(res); });
- 求二叉树的最大深度?(额这道题有点简单,我用的广度优先+层级遍历,递归当然也可以。)
interface Node { value: any; children: Node[]; } function maxDepth(root: Node) { if (!root) return 0; let queue: Node[] = []; let depth = 0; queue.push(root); while (queue.length) { let cur = queue.shift(); let times = queue.length; depth++; while (times) { cur = queue.shift(); for (let child of cur!.children) { queue.push(child); } times--; } } return depth; }
技术3面 (1h 10min)
三面主要是对之前面试(大三的时候投过字节,挂了)的问题重新进行考察,面了一道很有意思的算法题。
- 讲解一下 CSRF、XSS、SQL注入的攻击原理以及如何预防?(老生常谈的问题不讲解了。)
- 说一下 src 和 href 的区别?(主要在是否阻塞页面加载以及是否产生内容替换上,顺便提了一下浏览器的渲染过程。)
- 为什么 react16 设计了 fiber?(fiber的概念就是纤程,主要是提供一个可打断的异步渲染,设计渲染优先级,这是 react16 和之前版本 react 调和过程的主要区别。)
- DNS 解析过程?(主要讲了递归查询和迭代查询)
- 后端鉴权过程?(讲了 token、cookie、session、sso、以及项目中使用过的双 token 无感知刷新过程。)
- 问项目,因为我项目里写了一个接口管理平台,然后就问了我接口管理平台需要实现的核心技术点?(消息推送、项目以及接口权限设计、接口文档自动生成,swagger自动生成,mock自动化测试服务。)
- 一道 promise 的题,要求实现一个请求重发器,就是一旦失败就不断的重新请求直到请求超过最大次数限制,每次请求之间有固定的时间间隔,(这道题我一开始题目就读错了,我以为是一个超时与失败的重传器,写的直接裂开。)
- 扑克牌顺子算法,黑桃 0-12 红桃 13 - 25 方片 26 - 38 草花 39 - 51,给你随机的 6 张牌要求判断这六张牌里面有没有顺子?(这道题看起来难其实很简单,就是一道双指针,先对给定序列进行排序(排序前要先对每张牌取余 13),如果后一张牌比前一张牌大 1 那就当前计数加 1,如果不是那就重置计数,并且将本轮计数与规定的顺子长度进行比对。)
- 设计数据结构:需求是实现对电话号的智能提示,比如公司内网有 549... 和 546... 这两个号码,那么输入 54 之后要求能提示 6 和 9。(使用字典树也可以叫做前缀树就可以实现这个需求,前缀树一般在后端框架中用作实现动态路由。)
总结一下三轮技术面,前两轮的表现还算不错,第三轮虽然问的题不算难,但是面试官似乎不满意我的答案,导致做题的时候有点紧张,第一题题目还读错了,不过还好面试官手下留情放我去 hr 面了。字节的流程是很快的,基本每天面完之后下午就出通知了,就是 hr 面之后等意向书的过程有点痛苦,赶上国庆了,直接进行一个爆等。。。
最后祝各位面试顺利都能拿到自己想要的 offer (´▽`ʃ♡ƪ)。