2022 转职前端的海外求职与面试心得 (Amazon 与 ByteDance/TikTok 等)
2023年3月15日
嗨,相信妳会点入这篇文章,可能是因为妳看到转职前端的标题,也可能是有海外求职的打算。在往下读之前请先让我介绍自己,以及说说这篇心得会谈些什么。假如妳有觉得符合妳的需求再往下读,可能比较不会浪费时间 (因为文章会有点长 XD)。
我的背景是大学读文组,在 2020 年初透过 Alpha Camp 的实战课程转职软件业 (Alpha Camp 是一个线上 coding bootcamp,详见此)。 2021 年时,在有约一年半开发经验时首次海外求职(心得详见去年写的这两篇文章,《2021 转职前端工程师的海外求职(德荷英日新) 心得 I — coding bootcamp 之后的能力养成篇》、《2021 转职前端工程师的海外求职(德荷英日新) 心得 II — 找工作与面试篇》)
去年后来去了一间在柏林的新创公司,不过在待了一年后因为一些原因,所以决定换工作(详见这篇反思)。今年 (2022 年中旬) 算是带着两年半经验展开第二波海外求职之旅。今年这篇文章会先聊申请与准备概要,接着会分享实际的面试经验。这篇适合的读者,可能是 2 - 3 年经验的中阶工程师。如果是刚从 coding bootcamp 出来的工程师,我会比较推荐读我去年写的那两篇。
求职历程概述
虽说我先前在德国的公司,但今年德国的大公司反而都没有拿到任何面试 (例如 SAP、DeliveryHero 等)。另外就是,在德国或欧洲的程序员工作机会很多,但是大公司的机会没有比较多(虽然有不少各行各业的大公司,但多数都不是以软件为主),毕竟大公司也就只有那几间。所以我这次主要还是透过 LinkedIn 搜寻,然后被转去各大公司的招募官网自己投递。而我的投法,基本上是不看地点,觉得适切的职位就申请;因为对我来说,这阶段的目标是先进大厂,任何地点的大厂都可以。
而我这次自身经验是有拿到 Amazon (英国伦敦)、Booking.com (荷兰)、Twitch (APAC 远端)、ByteDance/TikTok (新加坡)、Shopee (新加坡) 等大公司的 OA 或面试。最后有录取 Amazon 与 ByteDance/TikTok。
从结果而论,虽然我有录取 FAANG 公司,也录取目前世界最大独角兽公司,但连面试都没发给我的公司不胜枚举 (基本上你想得到的国际软件大公司我都投了)。这让我深刻体会到,在不稳定的大环境下求职,真的蛮大一部分的因素不在自己的掌握中。举例来说,今年新加坡我也有投 Foodpanda,然后连面试都没有拿到,而在我投的当周,就看到他们新加坡办公室大裁员。而新加坡 Shopee 虽然有拿到面试,但 OA 与一面结束后,等了快三周没收到回覆,然后就看到新闻报导出他们大裁员 (九月底时),所以就没有后续。
因此,很可能不是因为个人的学经历、面试表现导致没拿到面试或没录取;申请者能做的,就是把简历编修到最好、面试准备充足,然后在机会来的时候,用尽全力把握住。
准备过程
这次我的准备分成两个部分,一部分是加强前端,因为 ByteDance 类的公司在这部分会问得很深入。我是直接找考古题,可以去稀土掘金上面找,或是上网搜「字节跳动面经」等面试心得。前端除了知识点外,也很常考前端白板题。前端白板题基本上就是能够自己写出各类效用函式 (例如 debounce
、 curry
、 deepClone
等等),以及能自己写出 Promise.all
这类方法。假如不知道怎么写的话,我在准备这次面试时,有整理了最常考的手写题与解答,欢迎参考《前端面试— 常考的 JavaScript 手写题总汇整》。
除此之外,我也有特别针对各个过去有使用过的函式库,去了解背后实作的原理。我去年就有被问到 Redux 的效能问题以及如何改善,假如没有理解 Redux 是如何被实作出来,就没办法跟面试官深度讨论如何改善其效能。这个准备方向也让我今年在面试,被问到 React Query 背后如何实作时,有办法跟面试官有一定深度的讨论。
另一部分则是资料结构与演算法白板题。去年我在准备时,先读过一次《Cracking the Coding Interview》,然后还看完 AlgoExpert 上的 160 题演算法题。也因为去年有花这些时间打基础,我今年就没有再用那两个资源,而是直接买 LeetCode Premium 来刷。会买 Premium 主要两个原因,一个是可以看到公司的标签,这点是基于我去年的惨痛教训,去年面 Shopee 新加坡被问到的演算法题,是该公司在 LeetCode 上的高频题,结果我没刷到,当下写不出来,面试就挂掉了。另一个买 Premium 原因是跑代码比较快,写错了重跑也不会有冷却时间,毕竟时间就是金钱,这点我觉得很有价值。
对于我去年写的资料结构与演算法准备心得,今年的我仍然会推荐 Google 工程师NeetCode 的频道 (它现在有出付费课程,但我觉得免费的NeetCode 150 就非常足够)。今年我额外推荐 Netflix 的资深工程师ThePrimeagen 在 Frontend Masters 上面开的演算法课程《The Last Algorithms Course You'll Need》。 Frontend Masters 其他课程要订阅费才能看,但这堂课是完全免费的 (非常佛心)。我觉得跟着 ThePrimeagen 的思考脉络,会对资料结构与演算法有新的一层理解,所以很推荐要打底的人可以上。
在练习刷题时,一定要练习边写边讲 (think aloud)。沟通思路可说是跟解题一样重要(这篇文章提到,题有解出来以为会过面试,结果后来没过,因为被认为沟通太差)。刚好 ExplainThis 的另一个共笔作者也有在准备刷题,所以我们每周末都会约一次帮彼此模拟面试。在实际面试前,我刷了约两个月,总共刷了快三百题 (几乎平均一天五题),其中一半以上是 Medium,次之是 Easy,Hard 没有写太多。
最后,我在这次的准备过程中,也陆续整理了一些笔记,有兴趣的人可以逛逛本站explainthis.io (未来会持续新增,欢迎关注)。以下分享各间公司的面试心得。
ByteDance/TikTok
ByteDance 是我最早面试的大厂,我面的是 TikTok 某个组的前端职位。这次面试下来,对 ByteDance 的印象就是效率非常惊人、速度非常快,早上投简历,下午收到面试邀约。每一轮也都是结束不到一小时,就收到下一轮的面试邀约。如果没有特别排比较晚的面试时间,ByteDance 应该可以在两周内完成面试。 ByteDance 已经是十万人以上规模的公司,还能维持这种效率与速度,怪不得底下的产品这几年海放竞争对手 (例如 TikTok 最近搞得 Snap 与 Meta 股价惨惨惨)。因为 ByteDance 在面试部分没特别签保密条款,加上网上多半也都直接分享题目,这边我也直接把遇到的提列出来。
一面 (资深工程师)
一开始先请我自我介绍,我有分享我转职的过程,有被问「决定转工程师后,为什么转职前端? 」。接着针对简历提问主要是针对过往专案与产品提问 (对过去用过的技术务必要好好复习),以及有问「做过最有挑战的专案」。
简历提问完后就是一连串的知识问答题。先从 React 开始问,先问了用过哪些 Hooks,然后追问useEffect
的实作(如网上的面经,在面 ByteDance 这类大厂,不能只会用某个东西,还需要能说出背后是如何实践的),具体追问了 dependency array 用途、背后机制,然后追问为什么 dependency array 是空的时候只会在 component mount 时执行、后面不执行? 如果 dependency array 传入物件或数组会怎么样? 如果传入 ref 会如何? 然后问useLayoutEffect
与useEffect
差别?分别适合的场景为何?
React 问完后问了比较基础的网路问题,主要针对 HTTP 提问,后面有追问 HTTP caching 的机制。追问eTag
与Last Modified
哪个优先? 为什么? 追问 304 的 response body 是什么? 为什么是如此? (这题算陷阱题,因为 304 没有 response body,关于 HTTP caching 的题目,可参考这篇)。
网路问题后换 JavaScript 题。这时就开启了线上 IDE (ByteDance 用自家的 Lark,里面可以一边视讯一边用线上 IDE,很方便)。进到 IDE 后,面试官先贴了一段代码,要我在不执行的状况下,说出代码的输出是什么 。基本上熟悉 Event Loop 与 Micro-task、Macro-task 运作,这题都能答对(详见这篇)。判读题我有顺利答对,于是接着进到 JavaScript 白板题,是要实作出 lodash 的.get
,我也顺利写出来(有兴趣的可以看《请实现 Lodash 的.get()》。
总的来说是密度很高的一场面试,60 分钟问好问满,有过往经历问题、有知识类问题(JavaScript、React、网路题都包含) 以及有手写类的白板题,算是很全面的一场面试。
二面 (团队的用人主管)
自我介绍后,针对简历提出一些技术讨论,有特别问我过去写单元测试、E2E 测试的经验。接着就进到知识类的问题,包含问了 JavaScript 中 Map 物件与一般物件有什么差别?都是键值对,为什么已经有了物件,后面还需要加入 Map? (这篇写很清楚推荐读读)
接着问了前端的各种趋势类问题 (我讲了蛮多最近社群讨论热烈的 Solid、Fresh、Qwik 等,以及他们解决了哪些其他前端框架遇到的问题)。然后因为我是写 React,被问到对 React 18 的理解。知识类的题告一段落后,最后由一题白板题结尾,是一题 LeetCode Medium 难度的字串处理,花了二十分钟左右顺利写出来。
三面 (整个大组的技术主管)
这个面试跟前没两关不太一样,没有自我介绍,一开始就直接来一题 LeetCode Medium,基本上是 3Sum 的变化题。因为是很熟的题型,所以我蛮快就解完了。解完后问 React 的问题,主要问 React Fiber 是为了解决什么过去的问题? 是如何实作的? 因为这题算是高频考古题,所以也有顺利答出来。接着问网路题,也是 HTTP 不过是针对 HTTPs 的 s 问,也是题高频考古题。最后有一题前端的系统设计题,花了二十分钟左右讨论如何设计一个 Typeahead 的前端。
三场技术面试下来,觉得 ByteDance 的面试真的很扎实,基本上每一关都有前端题与演算法题,而且三关着重的方向都稍有不同;三关下来从 JavaScript、React、CS 知识点,到前端的趋势与系统设计,几乎涵盖了各类题型。
四面 (人资)
顺利通过三关技术面试后,最后进到人资关。这关是由我面试的组的 HRBP 来面。 HRBP 有再介绍一下 ByteDance 的文化、我面的组在做的事。网路上也有不少人资关被刷掉的经历分享,所以这关也不能掉以轻心,各类行为面试的问题要好好准备。人资问的问题背后主要是看跟 ByteDance 文化的契合度,所以事先读一下公司文化会很有帮助。
在人资面之后一周后收到录取通知。 TA 也在通知时跟我说三轮技术面试的面试官分别给的反馈,三轮的反馈都蛮一致的,对我的沟通能力、前端知识掌握度、实际写程式能力(白板题) 三轮都是正面评价。但其中两个面试官有提到因为我过去没有实际做过大规模的产品,所以在经验这块他们会觉得还需要多累积。这个反馈其实正是我今年想要申请大厂的主要原因,我转工程师两年半来,做过最大的产品用户量级也不过日活二十万; TikTok 这种破亿用户量级的产品,真的是我缺少的经验。
Amazon
Amazon 我这次是海投数个不同办公室,结果唯一两个拿到 OA 与面试的,都在英国,一个是在爱丁堡办公室,另一个是伦敦办公室。有趣的是,一个是先 OA 后,没有 Phone Screen 直接 virtual onsite,另一个则是先 Phone Screen 后,没有 OA 直接进 virtual onsite。 virtual onsite 都是五轮的车轮战,可以选一天面完,或分成两个半天。因为我先前有连续面试经验,所以我很清楚一天三场面试是我的极限,所以我都选分两天。
特别备注,我投的都是前端工程师 (Front End Engineer 简称 FEE),而不是常见的软件开发工程师 (Software Development Engineer 简称 SDE)。我在伦敦办公室的 Phone Screen 轮有稍微跟面试官聊到,他说 SDE 基本上是全端,而 FEE 就是专注在前端。在 Amazon 这两者是有机会在内部申请转换的,那个面试官当初就是 SDE 进到 Amazon,但做了几年后想专注在前端,就转成 FEE。
面试的部分 SDE 跟 FEE 有些部分一样,但另一些地方不同。同样的地方是每轮都有一半是会问他们的 Leadership Principles 问题,也都会考资料结构与演算法。不同的地方是,FEE 可能会针对前端的知识点与实作来考。举例来说,在网路上有找到别人的面经是要当场实作一个元件。另外就是系统设计的部分,SDE 会考设计一个 Twitter,但是 FEE 则会是设计一个 Twitter 的前端(想了解更多的话,非常推荐这篇谈论前端系统设计的概览)。
爱丁堡办公室 OA
这次遇到的 OA 是两题 LeetCode Medium 难度的题。第一题我是用 Quick Select 来解;另一题是二维数组题目,这题可以 BFS 也可以 DFS,我是用 BFS 解。有趣的是,这个 OA 除了解题,还要妳用文字写下思路,以及分析时间与空间复杂度。
话说在 LeetCode 的讨论区中,很多人会回报自己 OA 遇到的题目,举例来说,在讨论区搜寻Amazon Online Assessment 可以看到我遇到的这两题,过去都有人回报有遇到。假如妳有拿到 Amazon 的 OA,推荐先去练习 LeetCode 讨论区被回报的题目,很可能会有一样的。特别注意,Amazon OA 是用 HackerRank,所以题目描述都很长,因此蛮推荐做之前先到 HackerRank 熟悉一下它们的题目描述方式以及平台的操作 。
伦敦办公室 Phone Screen
刚刚结束 Amazon 伦敦的 Phone Screen 轮,前面先是两题 Leadership Principles (LP) 题 (Amazon 的模式似乎都是这样),然后面试官都会一直追问。我先前就有在网路看到说,面 Amazon 在这部分一定要做足准备。实际面完的经验是觉得,不能只练习网路上找得到的题目,还需要练习后面的追问。
接着是两题白板题,大概都是 LeetCode Easy 到 Medium 的程度。之前在网路上看到 Google 面试是直接用 Google doc (而不是线上 IDE),Amazon 的 Phone Screen 也是蛮类似的,就是一个类似记事本的,然后没有任何功能。这两题都没有实际跑结果,感觉是以看思考过程为主 (先前面 ByteDance,因为就是实际在一个线上 IDE 所以都会实际跑面试官给的测试案例)。因为两题白板都没有太难,我都有顺利写出来 (起码面试官说逻辑没问题)。
这场 Phone Screen 让我意识到我之前太依赖 IDE 的方便了(因为我 LeetCode 有买 Premium,所以变得平常刷题也像是在 IDE 上写),所以这场之后在为实际面试准备时,我都先练习在 Google doc 上面。
Virtual Onsite
在分别通过前面轮次后,我申请的两个团队的招募协调员 (Recruitment Coordinator) 分别跟我约时间。但在乔时间的过程,他们内部似乎发现我同时在面两个团队,所以后来就来信跟我说其中一个的最后一轮会取消,不用面两次,而是假如没取消的那个有面过的话,最后会再分别跟两个团队的 Hiring Manager 谈要选择进哪个团队。必须说 Amazon 的招募员真的蛮雷的,敲定好面试的日期后,到面试前一天晚上才来信告知确切时间……。不过 Amazon 的每个面试官都非常专业,面试体验非常之好。
虽说我是面 FEE,但面试只有一关是由 Amazon 的 FEE 面,两关是 SDE,一关是 SDM 来面。因为有签面试的保密条款,不能分享详细遇到的题目,以下仅分享每一关的经验。
一面
面试官是 SDE,但他说他现在有约一半时间会做前端的东西,所以也会帮忙面 FEE。如同网路上看到几乎所有 Amazon 的 onsite 面试经验,果不其然一开始就来了两题 LP 题。接着进到前端实作,要做某个元件,可以用任何技术或框架 (我用 React)。虽然不能说实际做什么元件,不过假如网路上找的元件类题目都练过 (例如 Menu、Carousel、Accordion 等等等),这关就不会是太大问题。
我特别喜欢这关面试的地方在于,实作完后接着有一连串的追问,让前端面试变得很有脉络。虽然不能说被追问了什么题目,但假如上面我提到准备 ByteDance 的前端知识点都够熟,这些问题一定回答得出来。不过 ByteDance 在问的时候都是很独立的问题,例如上面提到我在 ByteDance 面试有被问「一般物件跟 Map 有什么差别」,假如只是这样独立问,我觉得在准备上就会有点像在背诵。但假如是写了某个元件,然后用到了物件,这时被问为什么不用 Map,然后两者间有什么区别,我觉得就会有脉络许多。
二面
面试官是 FEE。也是一开始就两题 LP 题,然后进到前端白板题。跟上一关不同,这关是比较偏向写演算法,但不是传统 LeetCode 那类的,而是像要写出某个框架提供的 API (某个函式),算是我过去没碰过的题型。如果要具体准备这类问题,可能可以多去看一些套件或框架的原始码,看看那些平常很常用到的 API 背后是如何实作的。我这关表现的没第一关好,虽然最后有写出来,但上一关有被问到如何优化代码,这关则是写完后时间就到,没有时间去优化解法。
三面
面试官是 SDE,他说他很喜欢 React 所以工作上也会去做前端的东西,但因为想让自己比较有弹性,所以没有转成 FEE,而是持续做 SDE。这关是很传统的资料结构与演算法题。当然前面也是先来个两题 LP 题,讲完后就进到算法的题目。一开始第一题是蛮中规中矩,用 DFS 或 BFS 就可以解的题目。解完后被问延伸问题,是要用 topological sort 来解。刚好我在面试前两周有刷了 LeetCode 上面的 Course Schedule 系列题,所以被问到延伸题时,就觉得题型很熟悉。只能说 Blind 75 这类经典题一定要每个题型都刷,对于各种类型与模式有概念,起码在面试时能有个底来面对变化题。
另外,因为不会执行程式,所以写完后,面试官都有请我用测试资料口头走过一次我的演算法。在这种类型的面试,对自己写的逻辑一定要够清楚,不能像平常写程式会依赖 debugger。面完后觉得好险前面有 Phone Screen 轮,让我意识到要练习用这种形式。
四面
面试官是 SDM,也是用人主管 (hiring manager)。这关是唯一没有写程式的,但有类似前端系统设计的题目 (只是不是传统类型的)。一开始面试官先连续三题 LP 题 (将近三十分钟)。接着是问类似系统设计的问题,会说是类似,是因为跟在网路上看到的题不太一样,但某些部分又一样。
因为不能提细节,只能说如果要准备这关,我会推荐多了解千万日活用户级别的产品,在前端的部分要怎么确保低延迟 (low latenecy)、高可用 (high availability)、高可靠 (high reliability)、安全性 (security),以及在千万日活用户级别的产品上一个前端的功能,要怎么规划整个流程等等。
这边蛮推荐大家可以平常多去看各家大厂是如何做事的,因为我这个 Loop Interview 是面 Amazon 的伦敦办公室,我在面试前有用平常吃饭时间爬他们的各种东西,然后就看到 YouTube 上的这个介绍伦敦办公室的影片。影片中有提到为了确保高可用性,Amazon 在上一个功能前,前端会测试几百种不同装置,确保都是可用的。因为看过那个影片,我在回答可用性的部分,有提了一个类似的作法,从反应上来看,面试官似乎对我的回答很满意,那时我心里暗自窃喜「毕竟这就是你们的作法呀 XDD」
面试后也是约一周左右收到结果,听到招募员说恭喜时,真的是又惊又喜;跟 ByteDance 不同,Amazon 的招募员说没办法给每关的具体反馈,不过有说每关的面试官反馈都很正面。以前都是看别人转职后进到 FAANG 公司的分享文,没想到转职两年半后,我也能听到 FAANG 公司的招募员跟我说恭喜录取。如上面提到,因为我本来是同时有拿到两个组的 onsite,所以后续还分别跟不同的用人主管聊,聊完后选完组,招募员才会发正式的 offer,然后谈薪水。在跟 Amazon 谈薪水时,有成功争取到提高 offer,相关经验都记录在《拿到 offer 后谈薪水— 让我多谈 35% 的谈薪笔记》。
Twitch
我是在找新加坡的职缺时看到的,不是一般的前端职缺,职位的名称是叫 Software Development Engineer, Customer Success。虽然是申请新加坡的职缺,但时面试都是跟美国那边的人面。同样是在亚洲区的缺,比起前面提到 ByteDance 的神速,Twitch 的动作就慢了不少,每一轮几乎都是等一到两周才通知结果。
一面 (人资)
这关基本上都是问求职动机、过去经历。人资也有更详细介绍这职位,我听下来感觉是介于 Software Development Engineer 与 Customer Sucess Engineer 之间的工作。工作内容以前端为重,但也会有牵涉到后端的部分,所以职位还是归在 SDE。在更深入了解后,人资有再向我确认有想申请,然后说后续会再联系。
二面 (资深工程师)
二面一开始也是问过去经历,问题包含过去做过最让自己引以为傲的专案、解决沟通冲突的经验等等。特别注意,因为这个职位不是纯开发,而是有部分时间要直接跟客户合作,协助客户整合 Amazon IVS 的服务 (这个职位在 Twitch,但产品是 Amazon IVS)。
接着问了不同程式语言的使用经验 (直译语言、编译语言),也问了不同浏览器的差异 (例如不同浏览器的引擎之间的差异),然后也问了前端效能优化问题。最后以一题白板题收尾,easy 到 medium,搭配 Stack 这个资料结构就可以蛮容易解掉。
二面后一周收到没有进到下一轮的通知,不确定原因是什么,毕竟二面不论在行为面试或技术面试,我觉得表现的都还不错,不会比我面 ByteDance 或 Amazon 还差,特别是效能优化题我觉得讲得够深够广、白板题解得很顺。但面试就是这样,总有各种原因导致没办法往下一阶段迈进。
Shopee
假如你有读过我去年的面试经验文,应该会看到去年我在 Shopee 二面的时候,在一题设计 LRU Cache 的资料结构题炸掉。今年想说再挑战一次,投了简历后也顺利拿到面试。跟去年一样先从 OA 开始,然后三轮技术面。我顺利的通过前两关,只是面到一半时,Shopee 似乎就大裁员,虽然感觉他们最近不太会招人,不过还是分享一下我前两关被问到的题目。
OA
字串长度要如何取得
- 这题是单选题,选项中有各种语言的语法,要选出 JavaScript 的
- 相信写 JavaScript 的人应该不会选错,这边附上 MDN 的文件当参考
考 JavaScript 的物件观念 (题目中的值不一样,但概念一样)
const x = { a: 20, b: 22 };
const y = x;
y.a = 30;
delete y.b;
console.log(x.a, x.b); // 30, undefined
考数组基础概念 (题目中的值不一样,但概念一样)
var a = [];
a.push("b");
a[20] = 22;
a[20] = undefined;
console.log(a.length); // 21,因为有 index 0 到 index 20,共 21 个
考字串基础概念 (题目中的值不一样,但概念一样)
a = "explain this";
a[0] = "i";
console.log(a[0]); // 'e' 因为 'explain this' 这字串的值本身没办法改
手写题一:写一个函式转换以下资料格式 (题目中的值不一样,但概念一样)
输入:
{
scheme: "https",
domain: "www.explainthis.io",
path: "item/search",
queryParams: {
page: 1,
keyword: "shoes"
}
}
输出:
https://www.explainthis.io/items/search?page=1&keyword=shoes
输入:
{
scheme: "https",
domain: "www.explainthis.io",
}
输出:
https://www.explainthis.io
最后一题跟我去年虾皮 OA 被问到的一模一样,是网路上找得到的**[Maximum sum of non-leaf nodes among all levels of the given binary tree](https://www.geeksforgeeks.org/ maximum-sum-of-non-leaf-nodes-among-all-levels-of-the-given-binary-tree/)**。
一面
一开始先请我介绍自己,接着就针对我的简历开始问问题。因为我在上一间公司与上上一间公司,分别有用过 React Query 跟 Redux,就被问了这两个工具做状态管理的差异相关问题,有被追问这两个工具要如何做选择。回答完后被接着追问 React Query 是如何实作的。这边要感谢先前在前端版看到有版大分享的《了解 SWR 的运作机制,How this async state manager works》一文,先前在理解这类套件的背后的实作时,这篇算是很清楚好懂的入门。
然后面试官接着问说「既然我们都聊到 cache,不如就来实作一个吧」。然后就开启线上编辑器,进到手写题的部分。这次的手写题第一题,是我去年 Shopee 一面的 cache 题进化版。简单来说,需要写出一个 cached 的函式,下面这个是我去年面试时写出来的,而去年的题目也就停在这边。
function cached(fn) {
const cache = {};
return (...args) => {
const key = JSON.stringify(args);
if (key in cache) {
return cache[key];
} else {
const val = fn(...args);
cache[key] = val;
return val;
}
};
}
上面这个写法会有个问题,就是假如今天传进来的引数是有函式的,用这个方法就会出错。今年这一题的其中一个测试案例,就是有函式作为引数的 (但去年没有)。那要怎么解决这问题呢? 我当时提说可以透过深比较 (deep equal) 来解决。面试官说,的确是一个解法,那不如你就写一个深比较吧。于是我又继续往下写了一个深比较的函式,才顺利通过这一题(有兴趣了解怎么写的人,蛮推荐这个影片的)。只能说,lodash 有提供的效用函式,手写题真的是前端面试必练的。
接着进到第二题,是要写一个改良版的 Promise.all
。 Promise.all
会要等到所有的实现,因此它的瓶颈会是最晚回来的那个,如果最慢那个拖很久,其他的也会要跟着等。但是这个改良版想做到的,是不要等全部实现,但又要做到有顺序性的回传结果。因为我先前练习过 Promise.all
与 Promise.race
等题目的手写,所以遇到这个变化题时,还算有办法应付。只能说许多 JavaScript 提供的方便东西,平时还是需要懂背后如何实践,不然面试被问时,我在想如果我先前没练习过相似的东西,应该很难在二十分钟想出来又写出来。
二面
去年我 Shopee 挂在二面,今年还想说把去年没写出来的 LRU cache 写个五遍,把 Doubly Linked List 的操作与题目都练很熟。结果一面之后 Shopee 新加坡就裁员。必须说,去年跟今年面试起来 Shopee 新加坡的面试算蛮有鉴别度的。不过现实世界就是只有技术没有用,如果没有永续的商业模式,最终还是撑不起一家企业。
Booking.com
OA
时间有 100 分钟,要用 Vanilla JS 写一个能做到 CRUD 的前端 (类似 Todo List)。因为我过去两年都写 React,所以 Vanilla JS 变的不太熟,虽然题目很简单,但我的代码写得很乱,被刷掉我也觉得合情合理。有要申请 Booking.com 的人,如果平常工作上都用框架,申请前要先好好补强 Vanilla JS,才不会跟我一样简单的东西还写得很乱。
Datafold
如开头提到,我今年的目标是进大厂,所以会面试 Datafold 其实是个意料之外的事,因为 Datafold 目前是在 A 轮融资阶段。会接触到 Datafold,是因为在欧洲有个很有名的软件工程作家Gergely Orosz (很推荐大家追踪他) 经营一个叫 Pragmatic Engineer 的网站,而该网站有个Talent Collective 的人才库。你可以申请让自己的简历被登入在人才库,然后该作家精挑细选的公司如果觉得你是适合他们的人才,就会主动联系你。被联系后你可以选择要不要跟他们面试。
Datafold 就是他们的人资透过那个人才库联系我。虽然我今年求职目标是大公司,但因为 Datafold 是 YC 孵化的公司,加上创办人本身是技术背景且有大厂经验,加上职位是全球远端+ 美国薪水(Datafold 前端工程师开的年薪是底薪 11 万到 20 万美元之间,基本上对于我的年资来说,是比各间大厂在欧洲区的薪水都还高)。总之因为这些条件,让我觉得是个值得一试的机会,所以就面了。而这也是我今年唯一面的一间新创公司。
一面 (人资)
都是问过去经验为主,假如有准备 behavior interview 应该这轮不会有太大问题。有被问到对于下一份工作的看法,因为 Datafold 算仍在新创阶段,所以可能讲的方向要偏向那方面一点(例如想要在迭代快一点的环境,想要有更大的影响力不想在大公司当小螺丝钉云云)。
二面 (工程主管)
也都是以过去经验为主,会针对简历上的技术点多挖一点。一面跟二面虽然都是问过去经验,但二面会比较是技术类的经验,例如会针对过去写测试的经验问(例如问单元测试、E2E 测试的概念与我过去实作的经验等) 。这关也会有一大部分时间让候选人问问题,我觉得整个面试有很双向的感觉 (就是真的深聊去了解彼此适不适合)。
三面 (资深前端工程师)
这关是技术面试,一开始先针对简历问,因为这关是我面完 Amazon 隔周面的,所以刚准备完 Amazon LP 题,在这关的简历问题就答的特别深入,感觉面试官觉得我分享的故事很不错。 LP 完之后是一个 code review 问题。
四面 (技术长)
这关也是技术面试,是我当工程师以来,最特别的一场技术面试。在一开始简单自我介绍后,被问到 React Hook 的问题,我概略地分享我的想法后,面试官就问说「你有想过怎么实现 React 的这些 Hook 吗?」,这时我就先举useState
为例,然后讲了一下我会如何实现;初步说完,面试官就说「不然我们来实际写一下吧」,这时我心里想,没想到这么硬,要当场写出 React Hook。
这时面试官竟然分享了自己的画面,我一时纳闷他为何分享画面,原来要写的人不是我是他。这真的是非常非常特别的面试,因为过去每场我遇过的技术面试,都是作为候选人的我写,没想到竟然会遇到一场是面试官写。总之我们就花了约五十分钟开始 pair programming。在过程中每写完一个段落,面试官就会提问题,例如「如果我们有多个useState
要如何确保在重新渲染时,原本的值会被记得且不会乱掉」,然后我就回答我的想法,就在这样一来一往中,把useState
实现出来。
回头看,我觉得我非常非常喜欢这场面试。因为是面试官写,某种程度上我的临场压力小了非常多;但同时因为过程中面试官会一直提问,所以他也能有效考察我对 JavaScript 与 React 的理解,以及我的思考。过去很常听人说把面试当成 pair programming,这场面试真的是我面过各类面试中,最有 pair programming 感觉的了。
同时这个面试方式也让我强烈感受到这个技术长的实力,作为一间做 data 产品的公司,该技术长的强项不是前端,但通过他的提问,我可以很直接感受到他如何思考,让我有「厉害的工程师,即使不是自己最常碰的领域,还是可以透过思考让自己在该领域有一定深度」的赞叹;以及他实际在写时,我看他写的代码,就觉得他写得真好。总之在这个互动过程后,我最直接的想法是「要是我跟着这个人一起工作,我一定能成长很多」。必须说,如果往后有人问我理想的面试形式,我绝对会提跟 Datafold 的这一场。
面试小结
前端工程各家大厂面试都不太一样,但如果用最高标准来准备每个面向,那不管遇到哪类都不怕。前端知识点用 ByteDance 的标准,在面对其他间的前端知识问题就觉得相对容易;刷题用 FAANG 的标准,在面其他公司时的刷题就觉得相对容易。
当然,用高标准来准备不是件轻松的事,特别是对前端工程师来说,深入的知识点、刷题在工作上很常没有直接的应用性,很可能在准备时就觉得「反正工作上用不到」就不读或不刷;然而就像运动员需要有大量而枯燥乏味的体能与重量训练,才有办法在自己的专项上有好的基础,准备面试过程读到比较深的东西时,如果愿意直球面对,把那些深入的知识点搞懂、把那些艰涩的题刷过,在面试时就能够比别的候选人有更扎实的基础、更突出的表现。
写在最后,感谢的话
和去年的文章结尾一样,最后免不了要说感谢的话。在准备面试上,真的是依靠前人们在网路上的分享,才让我能比较有方向性地准备。写这篇文也是希望能够回馈社群,让未来要面试的人有更多资料点能参考。当然如上面提到,很多时候大环境影响的因素更大,所以我的经验也不必然适用正在面试的妳/你,在阅读后还请多斟酌是否参考。
感谢读到最后的妳/你,也祝正在准备面试的每位开发者,都能在准备的过程中一步步踏实地向前迈进,最终拿到自己心中理想的机会 🙂