你好,欢迎进入江苏优软数字科技有限公司官网!

诚信、勤奋、创新、卓越

友好定价、专业客服支持、正版软件一站式服务提供

13262879759

工作日:9:00-22:00

字节前端社招面试复盘:八股文不够用,实际项目经验才是关键

发布时间:2025-03-18

浏览次数:0

[id_[[]66981]]

结论

通过

字节的面试经历颇为曲折。起初是某部门的 HR 直接与我取得联系。面了三轮之后,我感觉面试官的状态不太好,有些蔫蔫的。于是我咨询了在字节的朋友,之后决定更换部门。不过该部门的 HR 小姐姐非常好,她跟了我一个多月,还提前为我提供面试建议和辅导,希望她能找到更合适的候选人。

字节确实堪称宇宙厂,在当前的行情之下,仍有许多部门在进行招聘。由于之前拒绝过字节的 offer,并且有不少朋友在字节,所以我与好几个部门的领导通过微信进行了交流。之后,我选择了一个新的部门。前面流程中的三面通过,使得换部门后能够直接进入终面,这一点确实非常不错。

整体来看,字节的面试给我的感受是从技术到管理循序渐进,这一过程比较正常。在代码题方面,不再执着于某些特定类型的题目,而是换成了一些前端或业务可能会遇到的问题。对于我这样从来不刷题的算法渣而言,这确实是很不错的。最后,因为我目前的工作经历,导致有面试官的定级不一致,所以又加了一轮定级面。

一面

总时长:65min

这次换工作的首个面试,在 2023 年的行情背景下,我格外珍惜。因此,我做了很久的准备。然而,结果却让我失望,准备的内容一点都没派上用场。不过,好在问到的一些问题,凭借平时的积累,我还是能够勉强应付一下的。

面试官似乎不是很资深,面试以及代码都不算难。然而,自己的回答也不是特别出色,完全没有达到自身的预期和标准,因此对结果也没有十足的把握。

聊项目

可能是因为岗位的缘故吧,我原本准备了很长时间,可基础方面完全没有被问到,一开始就直接开始谈论项目了。这部分主要是由我自己在进行讲述,而面试官则穿插着问了一些问题,不过给人的感觉是技术性不是很强,大多都是比较开放性的问题。

我本身最擅长聊项目。然而,很多项目事先都没有准备,这导致项目的难度以及技术的复杂点都没有讲清楚。聊完这部分后,差不多过去了半个多小时。

后面就是针对于我的简历及项目情况问的一些具体的技术问题。

作为前端负责人在前端基础设施做了哪些事情

开发阶段包含了多方面的工作,包括技术选型,还有项目的创建,以及模板化的工作,同时也有脚手架工具等方面的内容。

在部署阶段,要知道怎样进行自动化的 CI/CD,还要知道怎样把项目部署到服务器。

质量有保证,会尝试运用一些自动化测试框架来对项目进行测试。并且会对项目配置进行收拢,降低配置的修改频率,以此来确保每个项目的基础设施保持统一。

如何提高效率呢?可以通过脚手架工具来达成零配置启动并部署项目的目的,还可以借助模板、组件以及相应的调用方式,以此降低开发门槛并提升效率。

Vite的底层原理是什么

这部分尚未去看。只了解它是基于某些东西并得以实现的,但仅就此便直接表示不知道了。

你觉得Vite相比于哪些方面更好

本地开发的构建速度较快。因为 Vite 是基于 ESM 的,所以在本地开发过程中,其整体的构建速度会比其他一些方式更快。

Vite 内置很多配置,使用起来很简单,能让开发者零配置就跑起一个项目。而另一些工具则需要写很多复杂的配置。

Vite的热更新原理是什么

Vite本地启动时会创建一个连接,同时去监听本地的文件变化

用户修改本地文件后,服务端能拿到变化文件的 ID 或者其他标识,然后将其推送给客户端。

客户端获取到发生变化的文件信息后,接着就会请求最新的文件,并且会刷新页面。

介绍一下之前的监控告警是怎么做的

分为两部分。第一部分是日志的埋点与上传,其中包含代码日志和业务日志。自己实现了一个以某日志服务为基础的系统,在客户端项目加载时启动,接着通过其提供的 log 方法在代码中进行日志打点。服务端收到上传的日志后,将其传入公司内的数仓,之后利用数仓的 API 实现日志的查询。

对于业务数据的埋点则是在对应的用户操作时进行埋点上报。

一部分是告警的实现,这是利用公司的统一基础设施来进行的。拿到前面的埋点信息后,在公司的告警平台能看到对应的埋点数据的趋势图。依据趋势可以设置告警阈值。告警阈值主要是由人工来指定告警策略,并且根据实际情况进行调整和优化,从而实现更准确的告警。

怎么去监控业务指标情况

通过业务流程中对应环节的埋点数据能够计算出业务指标。例如,提单成功率的计算方式为:支付成功的埋点数除以购物车页点击下单的埋点数。获取到各个业务指标的计算公式之后,就可以在告警平台配置对应的趋势图,接着按照之前的方式设置监控和告警就可以了。

小程序性能优化做了哪些事

小程序本身为双线程架构,渲染层与逻辑层相互独立,通过微信原生进行通信。所以性能的损耗主要体现在通信过程中。在通信过程中,影响性能的主要点在于通信的频率和数据量。

所以主要的优化手段是减少次数。同时,当数据量过大时,要对数据量进行拆分,分成多个部分去执行,然后从这两者之间找到平衡。

除此之外,利用了请求的预加载方式。

【代码题】实现一个React的 hook



const useState = defaultValue => {
const value = useRef(defaultValue);

const setValue = newValue => {
if (typeof newValue === 'function') {
value.current = newValue(value.current);
} else {
value.current = value;
}
}

// 触发组件的重新渲染
dispatchAction();

return [value, setValue];
}

二面

总时长:60min

D2C做了哪些事情

主要做了一个插件,是通过插件的开发语言以及其中的方式来达成的。为降低开发成本,插件面板内的所有内容都是在内部开发前端页面。当从面板中拖拽某个图标或组件出来时,会把组件的信息传递到插件原生中,然后通过开发文件的查找以及放置画板的逻辑来处理。

为了实现简单化,在插件安装时我们内置了符合业务规范的组件包。这样一来,面板中的每个组件都有唯一标识,且该标识与组件是一一对应的。最后在导出页面时,也是对画板中的模板和组件进行遍历,从而找到对应的组件代码并进行组装。

小程序的日志和监控服务做了哪些事情

分为两部分,第一部分为日志的埋点和上传,包含了代码日志和业务日志。主要是自己实现了一个基于的日志服务,在客户端项目加载的时候启动,然后通过提供的log方法在代码中去进行日志打点。服务端收到上传的日志之后传入到公司内的数仓,之后通过数仓的API实现日志的查询。

对于业务数据的埋点则是在对应的用户操作时进行埋点上报。

另一部分则是告警的实现,这部分利用公司的统一基础设施去做。在拿到前面的埋点信息之后,在公司的告警平台可以看到对应的埋点数据的趋势图,根据趋势可以设置告警阈值。告警阈值主要是通过人工去指定告警策略并根据实际情况进行调整和优化,以实现更准确的告警。

作为前端负责人在技术上做了哪些基建

脚手架

提供前端脚手架工具,它可以支持通过一行代码来自动完成项目的创建。并且在创建项目的同时,还能调用相关的 API 去完成远程仓库的创建。最后,还能够自动生成相应的 CI/CD 脚本,以实现自动化部署。

将项目的配置项进行收拢。其中包含 Vite 等相关内容。把标准的配置文件都内置到脚手架里,仅提供部分配置项以单独的脚手架配置项的形式展现出来。

提供的自动化命令涵盖了代码格式化、质量检测、本地开发以及生产打包等方面。

框架

前端框架部分主要做了以下工作:对一些公共模块和服务进行了单独的封装。这些公共模块和服务包含请求模块、状态管理以及路由等。并且,所有的功能都由框架导出,以便开发者能够直接调用。

封装了业务通用能力,其中包括 PDF 预览、统一图表展示以及富文本编辑器等。

组件

组件部分主要是以 Antd 为基础,进行一些样式方面的处理以及改造,同时还进行了更上层的组件封装。

将常见的 CRUD 页面封装为模板,同时提供其使用方式,这样就能通过 JSON 配置直接生成页面。

富文本编辑器是如何实现的

一开始是借助 slate.js 来实现的,slate.js 赋予了富文本编辑器核心能力,凭借这些核心能力我们能够在其上构建各种复杂的富文本编辑器。然而,随着业务对富文本编辑器的功能需求不断增加,我们就必须在 slate.js 上投入更多的人力去开发这些新的功能需求,这在我们这样的小团队中显然是不太可行的。于是考虑寻找一款功能完备的富文本编辑器,最终选定了 jodit,它是一款以 TS 实现的富文本编辑器,其整体代码较为容易阅读,利于后续对它进行二次开发。

有没有在质量和稳定性上做一些事情

包含两部分内容。一部分是开发过程中的质量保障,主要有两点:其一为单元测试,通过 Jest 来实现;其二是 UI 的自动化测试,通过特定方式实现。第二部分是对线上稳定性的监控,此部分是基于开源项目并进行二次开发而实现的。具体可分为以下几个步骤:

对异常进行分类,不同的分类采用不同的捕获方式。比如用('error')来监听 JS 代码的异常,用.来监听资源加载的异常,用 xhr.('error')来监听请求的异常等。

可以进行上报,也可以直接通过 HTTP 请求上报。在上报时,要考虑到弱网的缓存情况,还要考虑到高并发的数据合并情况。

启动一个 Node 服务,当接收到异常数据时,就将其直接存储在数据库中。

对上传的异常数据进行分类查询,同时对监控数据也进行分类查询,并且提供与之对应的监控告警机制,在数据超出阈值范围时,就会发送告警邮件。

【代码题】描述下列代码的输出结果和原因



这种题目最让人害怕,总是让人想不明白。一开始就告知结果是 3,接着面试官又让我再思考思考。
仔细梳理之后发现,fn()里的函数声明会提前,不过不会提前到最外层,只会提前到 fn()的顶层。
里面的 foo = 3 所进行的修改,实际上是针对里面函数的那个声明进行的,这种修改不会对外部产生影响,所以最终的结果应当是 1。

var foo = 1;
function fn() {
foo = 3;
return;
funciton foo() {
// todo
}
}
fn();
console.log(foo);

【代码题】按照版本号由小到大排序

有['0.1.1', '2.3.3', '0.302.1', '4.2', '4.3.5', '4.3.4.5']这些内容。

输出包含以下内容:['0.1.1', '0.302.1', '2.3.3', '4.3.4.5', '4.3.5']



function compareVersions(versions) {
return versions.sort((a, b) => {
const tempA = a.split('.');
const tempB = b.split('.');
const maxLen = Math.max(tempA.length, tempB.length);
for (let i = 0; i < maxLen; i++ ) {
const valueA = +tempA[i] || 0;
const valueB = +tempB[i] || 0;
if (valueA === valueB) {
continue;
}
return valueA - valueB;
}
return 0;
});
}

三面

总时长:80min

三面的问题均在预期范围内,自己事先做了一些准备。因此,整体回答较为系统且全面。最后的代码题难度不大,这种贴近实际业务的题目比之前的题要让人感觉更舒适。不过,一开始考虑得不够全面,在面试官提醒后进行了补全。

时间有三面,且不短。我唯一所担心的是,我的项目经历在技术复杂度方面较为一般,或许会与面试官的期望不相符合。

介绍一下业务做了哪些系统

从现在公司的业务开始讲,接着依据业务内容介绍了相应的系统,我认为这个问题主要体现的是自身对业务的理解。

在以往的工作经历中有哪些最有成就感的项目

之前做的监控和告警项目进行了详细讲解,还说明了如何借助技术手段推导业务指标,以及怎样根据业务指标的监控数据反推业务的发展。对具体技术上的关键点做了细致介绍,然而整体的复杂度并不高,主要从收益方面来看,属于低成本高收益的项目。

当时为什么考虑现在的公司

从三个方面进行考虑:

在互联网行业待了有一段时间了,很想看看其他行业的样子。并且,自己对金融一直都比较感兴趣。

大厂“打螺丝”这种工作方式无法充分展现自身价值,人们希望能够前往小公司,去做更多种类的事情,从而让自己变得更加全面。

具备一定的创业精神后,若选择了一个创业团队,便能够获得一些创业方面的经验。

现在为什么又要从现在的公司离开

有两个原因:

团队发展前景不被看好。新来了一位老板,这使得团队的定位有了改变。原本是创新的探索性团队,如今变成了支持性的 IT 团队,这与自身的期望不相符合。

个人发展受限:从技术方面来讲,产品的用户数量不多,并且复杂度也不高,技术方面一直在进行输出工作,然而输入方面却非常少;从管理方面来看,团队的规模已经趋于稳定,在后续不会再有更多的人需要自己来带领。

对自己未来的发展规划是什么

也是可以从两个方面来讲,一个走技术路线sketch画板排序,一个走管理路线。

技术路线:

持续精进自身已掌握的技术,并且利用技术手段来回馈团队和业务,像在前端架构方面、进行异常监控、进行性能优化以及构建指标体系等。

在某一技术方向上取得突出成就,能够提炼出相应的方法论,并且构建出系统性的平台,在部门内部以及公司内部进行普及和应用。

保持对新技术怀有热情,持续拓宽技术的广度,对团队的技术栈不断进行迭代,以保持团队整体技术的竞争力。

管理路线:

定目标 —— 包含业务支撑、技术成长和团队培养三部分

进行执行,主要是梳理现有流程存在的问题,使过程更加规范且流程化,同时要发掘有高潜力的方面,为其提供快速成长的空间

拿结果 —— 需要有可量化的具体数据来作为结果的衡量依据

【代码题】实现一个拼手气抢红包算法

提供了一个类,在初始化时需要传入红包的金额以及个数。这个类需要实现一个方法,每调用一次该方法就进行一次“抢红包”的操作,并且要以.log 的形式将抢到的红包金额输出出来。



class RedPackage {
money = 0;
count = 0;
_remain = 0;

constructor(money, count) {
this.money = money;
this.count = count;
this._remain = money;
}

openRedPackge() {
// 已经抢完了
if (this.count <= 0) {
console.log('红包已经被抢完啦~');
return;
}

// 只剩一个红包
if (this.count === 1) {
this.count--;
console.log(this._remain);
return;
}

const ratio = Math.random() * (this._remain / this.money);
// 这里会涉及到一个JS计算精度的问题
正常情况下需要借助第三方库或者运用字符串算法来达成一个精确的加减乘除操作。
// 这里为了简单就这么直接做了
let youGet = (this.money * ratio).toFixed(2);
const tempRemain = +(this._remain - youGet).toFixed(2);
const allLeast = this.count * 0.01;

如果剩余的金额无法满足每人一分钱的需求,那么就需要降低本次所获得的金额。
if (tempRemain < allLeast) {
youGet = +(this._remain - allLeast).toFixed(2);
this._remain = allLeast;
} else {
this._remain = tempRemain;
}
console.log(youGet);
this.count--;
}
}

换部门三面

总时长:60min

前面已经完成了三轮面试,经过一系列的调查和询问后,最终决定换到新的部门。因为前面三轮都通过了,所以过来之后直接进入终面。这一面聊的内容不是很困难,但能感觉出面试官很资深。最后一个简单的代码题我写得很糟糕,差点没写出来。今年写代码的状态确实不佳。

聊项目和经历

这一轮没有询问很多具体的前端技术。主要聊的是过往的项目以及工作经历。聊的时候比较轻松。但这种情况让人有些没底。不知道面试官那里的反馈是好还是不好。

【代码题】数字转字符串

样例输入:

样例输出:1,234,567,890



function toString(num) {
// 这是最简单的写法
将数字转换为本地字符串格式并返回。
const result = [];
const str = `${num}`.split('').reverse();
for (let i = 0; i < str.length; i++) {
if (i && i % 3 === 0) {
result.push(',');
}
result.push(str[i]);
}
return result.reverse().join('');
}

定级面

总时长:25min

三面聊完后,HR 很快联系了我。HR 告诉我通过了,但职级方面存在一些问题,需要我参加一轮定级面。我虽然不太情愿,但也只能答应。等到面试时,情况挺出乎意料。面试官很直接,上来没让我自我介绍,直接让我打开白板画一个架构图,然后就依据这个图进行讲解,之后面试很快就结束了。

画一个自己做过的最复杂项目的架构图

这个结果挺让我意外。因为我的飞书是老版本,不具备白板功能sketch画板排序,所以后来就挑选了一张之前画过的前端架构图来进行讲解。这部分就不详细展开了。讲完之后,我感觉自己的内容似乎很简单,没有让面试官感到满意。

有想看这个架构图的可以在这里自取~ 模板社区-前端架构图

如何理解业务的

这个问题与前面第一次三面的第一个问题的回答相近。首先会介绍公司所做的业务,接着结合业务来介绍对应的系统,最后讲述每个系统的功能。

最后

还没有使用过我们的刷题网站或者前端面试题宝典的同学,如果近期有找工作的打算或者正在找工作,那么千万不要错过。我们的题库主要有两个特点,一是无广告,二是更新快。

老规矩,也给我们团队的辅导服务打个广告。

原文链接:

如有侵权请联系删除!

13262879759

微信二维码