阅读 24953

一年半经验前端社招7家大厂&独角兽全过经历 | 掘金技术征文

前言

在鹅厂也呆了一年多了,业务一般,主要是太忙,没有时间喘气,没有时间规划人生。希望能换个更轻松的工作,所以出来看机会了。个人选择的原则:至少满足工作生活平衡(硬性条件)、付出收益平衡、业务未来可观

这次近3个星期,面了7家(拼多多、虾皮、作业帮、猿辅导、商汤科技、快手),全都是线上视频面试的,一般是晚上回家面试或者周末。过程还是挺顺利的,全都过了。时间很紧凑,几乎没什么时间准备和复盘,一环接着一环的,所以就全部凑到一起一次性总结了

下面的面试题,会给出一些参考思路,也会标明每一题的性质,如下:

  • 描述:对概念、过程的描述,纯理论性问答题为主
  • 举例:说出应用场景,或者是自己团队实践的情况
  • 伪代码:写代码,但不需要跑起来,可以随便写,主要目的是描述思路
  • 编程:真正的写代码,需要跑起来,有测试用例,要看到效果

拼多多

公司面试难度评估:✭✭✭✩✩

1面

pdd用的是他们自己家的面试系统,该有的功能都有,和牛客类似,web-ide体验稍微差一些。

  1. react16新生命周期,有什么变化【描述】

两个static、一个didcatch捕获错误的、一个getsnapshot

  1. react16之前的那些不好的生命周期怎么过度到react16的新生命周期【描述】【举例】

getDriverStateFromProps替代componentWillReceiveProps,加上逻辑对比上次state和props来决定state。willupdate换成getSnapshotBeforeUpdate,willmount直接写成初始state(react16的state不先写出来是null,你需要先在class组件里面写一下state = {...})

  1. componentWillReceiveProps用到了this,getDriverStateFromProps也要用,怎么办【伪代码】

把this.xxx存到state里面,第二个参数是state,里面有xxx(有点挫,懂的人应该都有同样的感受吧,如果是函数组件,一个useRef保存一下即可)。另外的方法,如果和内部变量无关,把它抠到class组件外面去

  1. 编程题:求最大公共前缀,如['aaafsd', 'aawwewer', 'aaddfff'] => 'aa'(ide没有调试功能,也不能打开控制台,我只能写好了让面试官去运行。无调试,靠想象)【编程】

  2. 编程题:求最大公共路径前缀,['aa/bb/sd', 'aa/bb/wwewer', 'aa/bb/ddfff'] => 'aa/bb'(无调试,靠想象)【编程】 接上题改一下,不用一分钟即可解决

  3. 怎么理解ts【描述】

类型检查、ide友好提示、文档、利于维护

  1. ts的type和interface什么区别【描述】

经典问题,网上可搜,主要是列举出两者的特点,对比一下

  1. ssr怎么实现,你们怎么做【描述】【举例】

将动态渲染逻辑做到后端去,并把最终html结果直接返回。我们这边是数据动静分离+部分ssr直出,重要的数据ssr,比较慢的接口还是放前端

  1. 你们有没有统一构建的cli,怎么实现【描述】【举例】

基于react全家桶,ts、eslint、埋点上报、sw都可配置,根据配置生成代码模版,开箱即用

  1. 你们项目有ci吗,怎么做,提交的时候会做什么事情【描述】【举例】

通过接入公司内部某ci,配置yaml文件,每次监听git hook,并作出对应的行为如安装、lint、部署、搬运、生成change log等等。提交的时候,检查lint、修复autofixable的问题,存在修不了的问题报错,提交失败

  1. e2e测试、自动化测试【描述】

概念性问题,网上容易搜到。端对端测试,模拟用户行为对网页进行全流程测试;自动化测试,包含很多了,范围更高一个维度

  1. git rebase什么作用【描述】

概念性问题

一面的面试官很友好,虽然戴口罩,但也可以感觉到满满的笑容。面试过程中,我的问题还没问够,他说你可以问2面面试官

2面

面试官说系统有问题,开不了摄像头,于是加了微信,微信电话+系统在线写代码结合。不得不说,pdd这个系统很严格,我拖一下窗口就说作弊警告,然后接了一下面试官微信电话又作弊警告,面试官说问题不大,不慌。面试官很严格,全程一本正经,虽然没看见人,但强大的气场让我有一点心凉的感觉

  1. 项目介绍【描述】

  2. 项目难点【描述】【举例】

一定要拿出最熟悉最自信最能体现自己的项目,这一块是确定面试表现的关键环节。面试中这里可以问个半小时以上。包装假项目的、吹牛的,到这里基本就可以区分出来了。还有项目比较浅的,到这里如果进入尬聊或者冷场,很可能就挂了的。反正我是可以保证自己掌控主动权的,让面试官跟我思路走

  1. 实现一个redux【编程】

还是那10几行经典redux,途中会顺便问一下函数式编程、纯函数、副作用这些,网上搜“函数式编程”即可知道这些概念了

  1. 如果是用ts写,怎么写【编程】

改成ts版本,如果比较熟悉redux+ts的,很快写出来。如果不太熟,熟悉泛型也可以根据表现,很快写出近似的。我说我没有ide提示,不能保证裸写没问题。面试官说没事,只是看看你ts熟悉程度

小结

pdd钱给的很多,算是top水平的了,base低的可以去pdd搞一波,快速提升base和pkg。但是pdd单休,平时加班很晚,项目节奏很快很紧凑,所以还是看个人取舍吧。

虾皮

公司面试难度评估:✭✭✭✩✩

1面

  1. 项目突出点,挖项目细节问题【描述】

  2. 各种情况下的proto指向,多道问答题【描述】

有一个class A {},问他的实例a的__proto__A.prototype的关系,a.__proto__.__proto__是什么,a.__proto__.__proto__.__proto__是什么。然后再问普通对象、function的。这里需要注意一下Function.prototype === Function.__proto__和a的三次proto是null。一开始就问三次取a的proto,其实潜意识是null的,但刚刚下班赶车回家,心跳都没有恢复正常就进入面试,没什么状态,“em~”了10秒钟,面试官说:哎,你别打开控制台喔,别偷偷的运行哦。我说这肯定是原型链终点了,我想想,确认一下——null!犹豫就会败北,开门一波丢脸

  1. 页面10张img,http1是怎样的加载表现,怎么解决。那多域名又为什么可以解决呢【描述】

这个是面试重点高频率问题之一,http1下,浏览器对一个域名下最大tcp连接数为6,所以10张图片表现为6+4。所以可以用多域名部署解决。5个a域名,5个b域名就可以实现一瞬间全部出来了(或者6个a,4个b,融会贯通)。如果是1个a域名,9个多域名,会表现为(6 + 1) + 3

  1. http缓存是怎样的。etag和last modify分别什么优点缺点,适合什么场景【描述】【举例】

缓存、304基本问题。etag适合重要量小的资源,last modify适合不重要的量大的资源。注意last modify需要保证服务器时间准确

  1. 接上题,10张img,http2是怎样表现【描述】

一瞬间全部

  1. http2为什么快,多了什么特性,头部压缩算法是怎样【描述】

背书,搜http2答案都有了。头部压缩是HPACK算法

  1. react性能优化【描述】【举例】

scu生命周期、memo;usememo & usecallback记住一些值不用重新计算;虚拟列表;immutable+scu/memo;原生js;(这块聊了很久了)

  1. 长列表优化,多种方案及对比【举例】

虚拟列表、intersectionobserver、监听滚动长列表+raf(经验之谈,聊了很久)

  1. diff算法、key作用,不要key会怎样【描述】

树diff、组件diff、元素diff;key可以原地复用,没有key无脑会更新(此时你可以发现,index做key其实会形同虚设)

  1. react的usememo原理【描述】

闭包、缓存、memorize

  1. 编程题:对象扁平化【编程】(30min)
{
  "a": {
    "b": {
      "c": {
        "d": 1
      }
    }
  },
  "aa": 2,
  "c": [
    1,
    2
  ]
} =>
{ 'a.b.c.d': 1, aa: 2, 'c[0]': 1, 'c[1]': 2 }
复制代码

我一听到30分钟,心里暗暗的想,给30分钟是不是觉得我很菜啊。不管他,先撸为敬。reduce递归+ ...,写+debug总共4分钟就秒杀了,面试官说你怎么不写了,我说已经ok了。他看了一下,嗯,ok

主要是一开始问proto冷场了10秒,这么基础的题都犹豫了,有点丢脸了,还好后面力挽狂澜把局面拉回来了。后面因为提前做完题目,和面试官聊了很久其他事情了,业务、技术、团队、公司方向之类的,到了7点了,他说后面其他的你问hr吧(潜台词:你过了)。总的来说,面试官是那种逗比类型的,面试过程中和一个人闲聊一样,有说有笑,挺爽的

2面

  1. 项目相关,细问【描述】【举例】

这里还是问项目。对方以前也是腾讯的,我们也聊了很多腾讯内部相关的事情,挺多共同话题的

  1. 如果我接入你做的平台,怎么接入【举例】

项目继续挖。我们互相之间说了很多腾讯人特有黑话,拉近感情

  1. jsbridge了解么,说一下【举例】

没做过,就我之前做少量内嵌webview的经验,我猜一下吧,大概就是两种:注入全局方法通信、监听url协议(如abc://,然后触发请求的地方可以做拦截如img、iframe、xhr、fetch等)。回去查了一下,发现我猜的的确是差不多,只是专业名词没到位,口头话很多

  1. addeventlistener第三个参数作用【描述】【举例】

控制冒泡/捕获阶段执行。或者是一个对象{ passive: true },针对的是Safari的,禁止/开启使用滚动的时候要用到

  1. cjs和esm区别【描述】

概念性问题

  1. 为什么浏览器不用cjs而用了esm【举例】

个人观点类问题。cjs都是require系统本地文件,时间不用考虑。如果在浏览器使用类似cjs的require,实现过程无非就是创建script标签、发请求。这个发请求的过程就无法保证同步了,你要写成callback/promise/async-await,这样子写页面门槛又高了

  1. es6了解不,说一下let、const的暂时性死区【描述】

概念性问题。没变量提升了,提前用会报错

  1. set、map有什么好处,map和一般的对象有什么不一样【描述】

概念性问题。map可以用复杂数据类型做key

  1. 跨端的方案【描述】

内嵌webview、客户端内嵌js引擎、将js编译为客户端语言运行

  1. 编程题:字符串相乘【编程】

实际上你可以理解为大数相乘。总体很快写出来,但是自己debug的时候,花了很长很长时间,因为在debug的时候console了一下index,发现index居然错位,疯狂怀疑人生,尴尬。最终找到了原因(哭笑不得)——每次面试牛客网编辑器有一个console.log('hello world')的,我一般不会删掉。这次我居然删了,导致什么现象呢,就是这样:

输出结果: 0
1
复制代码

而我期望的是

输出结果: 
0
1
复制代码

如果你不删掉系统默认的一句hello world,用的时候0在第二行开始,不会觉得有什么问题

输出结果: hello world
0
1
复制代码

突然删掉console.log('hello world'),目光直接到第二行,第一个index是1!那种心情。。。写代码几分钟,傻乎乎debug20分钟。面试官说,看你coding挺欢乐的,不错。我说看错这个console了,害得我白搞那么久。他说没事,问题不大

二面面试官,每次我说完一个问题,他都会说“谢谢”,挺有意思的。后面闲聊了很久,到7点了,我说虾皮下班时间到了,差不多了吧。他说陪你继续聊聊,没事的(暗示:你过了)。然后又多聊了20分钟,最后他再次重复了他们的业务,然后我也问了一下语言、app国际化方案怎么做,收获挺大的

小结

虾皮是毕业一两年内性价比最高的了,工资高,福利好,每天7点下班,而且在海外电商方面很有潜力。目前我所看见的虾皮,在大家口中几乎是没有差评的

作业帮

公司面试难度评估:✭✭✩✩✩

1面

  1. 一堆看代码说输出的题【描述】

就是this、变量提升、闭包、event loop说输出的那些基础题。这些必须秒答出来且答对,基础一定不能有差错。到了这个阶段,这些题应该是送温暖的

  1. 项目介绍【描述】

  2. cache-loader有什么坑,缓存错误怎么解决【描述】【举例】

面试官提到,他们做一个可视化编辑页面的系统,对组件使用了cache-loader,开发中有时候出现缓存错误的文件的问题。他说他们遇到了这个问题,暂时没有解决,叫我猜想一下,可能是什么原因导致的。我说应该是开发过程中,修改了被引用模块/引用模块、或者切换git分支,需要自己删除掉node_modules/.cache或者重启dev server。

  1. 编程题,9选3(15min)【编程】
  • 实现bind(送分)
  • 防抖&节流(送分)
  • settimeout实现interval(注意和普通的要无差别体验)
;(() => {
  const list = new Set();
  function myInterval(fn, ms) {
    const ref = {};
    const exec = () => {
      return setTimeout(() => {
        fn.apply(null);
        const timer = exec();
        ref.current = timer;
      }, ms);
    };
    ref.current = exec();
    list.add(ref);
    return ref;
  }

  function myClearInterval(ref) {
    clearTimeout(ref.current);
    list.delete(ref);
  }
  window.myInterval = myInterval;
  window.myClearInterval = myClearInterval;
})()
复制代码
  • 字符串大小写反转(送分) 节点是不是属于某个节点下(当时我写了一个不带parentid的版本,要自己一层层搜。如果带parentid的,就简单很多了,测试用例你自己写,他们也没有给出)
  • 反转链表(常规题)
  • 合并数组['a', 'b'], [1, 2, 3] => ['a', 1, 'b', 2, 3] (送分)
  • 合并有序数组 [1, 5], [2, 5, 6, 8] => [1, 2, 5, 5, 6, 8] (常规题,而且比合并有序链表还要简单一些)
  • 一堆数字字符串组成最大数是多少[50, 2, 5, 9] => 95502 (字典序+贪心)
function getMaxNumber(arr) {
  return arr.sort().reduce((acc = '', cur) => Math.max(+`${acc}${cur}`, +`${cur}${acc}`));
}
复制代码

都属于比较简单的且经典的,可以当作练练手。毫不夸张的说,实现interval和最后一题稍微能扛多一阵,其他的那些经典的题,如果大家平时了解过的都可以秒杀的。

编程题说9选3,但是作为有追求的人,除了面试过了拿offer,还应该追求高评价,拿到更多的薪水和更高的定级。那么,15分钟内甚至10分钟内,把它们全部写了吧。平均每题不用1分钟,单链表和判断节点祖先花了一点时间写测试用例。我是从最后一题开始倒着做的,面试官看着都呵呵笑了,说继续干,有时间就继续,可以可以!最后口头问了一下如何判断链表有没有环,我说快慢指针。

2面

  1. 说项目,深挖【描述】

  2. react生命周期和diff算法【描述】

新的、旧的,hook替代的。树、组件、列表三种diff(故意引话题,等他问key)

  1. key的作用【描述】

复用元素,描述一下有key的列表diff过程(果然问了key)

  1. 内部系统配置页面不写或少写代码的实现思路【描述】【举例】

新建页面 => 设置配置、db => 新页面onload => 拉配置,根据db的字段和配置渲染表格 => 配置不能满足的使用装饰器劫持实现个性化 => 业务代码&框架代码分离(微前端架构)

  1. 多框架、历史页面怎么解决【举例】

旧页面iframe、新页面走上面的流程,多框架使用external + 动态引入

后面我问问题的时候,发现他们的基础设施、开发流程有一些可以优化的地方,我说了一些自己的看法,面试官挺开心的样子,说回去看一下

小结

这次社招面试中最简单的一家了,全程很轻松,并且掌握了主动权把控面试节奏。cache-loader有什么坑,缓存错误怎么解决,这个问题我也没遇到过,面试的回答只是根据作用来猜想的,路过的有人知道或者遇到的话可以分享一下。

猿辅导

公司面试难度评估:✭✭✭✭✭

1面

  1. react生命周期介绍,怎么执行。说一下下面的组件生命周期执行顺序【描述】有<A> <B /> </A>这样的组件:
a.willMount 3
b.willMount 1
a.didMount 4
b.didMount 2
复制代码

react16前是递归的,是这个顺序。react16后改成fiber架构,是反过来的了,没有像栈那样fifo

  1. redux vs context,为什么不用context【描述】

随意修改,莫名其妙的bug。redux将这个过程规范化,单向数据流

  1. react 17要做什么规划,concurrent mode【描述】

concurrent mode、去掉危险的生命周期。concurrent mode是react重点面试题了,基于requestidlecallback实现(考虑兼容性,官方自己实现了一个)——浏览器空闲的时候做事情

  1. SSR,打开你们的SSR页面看看,具体逻辑、实现方式【描述】

发了一个我们的链接给他,并描述了流程

  1. promise.then(f1, f2)``和promise.then(f1).catch(f2)区别【描述】

捕获全部上游和捕获本次then

  1. () => {} vs function () {}【描述】

送分。无argument、this是定义那一层、箭头可以指向返回值

  1. 说输出【描述】
const obj = {
  f1: () => console.log(this),
  f2() { console.log(this) },
};
obj.f1() // global
obj.f2() // obj
new obj.f1; // instance
new obj.f2; // instance
复制代码
  1. Map/Set、WeakMap,什么作用【描述】

map可以用对象做key,set做集合使用。WeakMap弱引用,防止内存泄露

  1. 用setTimeout实现setInterval【编程】

又问到了,频率有点高

  1. Node { value: number; children: Node[] },算出树每一层节点和,输出数组【编程】

     2         => 2

2      3      5  => 10

1   2  3   4   7 8 => 25

// 每一层的和 [2, 10, 25];
复制代码

使用bfs可秒杀

1面中规中矩,面试官语速比较慢,听起来无压力,很轻松。后面问问题发现我做的一些东西和他们的差不多,感觉也是无缝衔接。然后了解到了公司下班时间也很早,福利也很好

2面

1.节流、和防抖的区别,均匀的节流怎么实现【编程】

一下子写了最简单的出来,然后他要各种改需求,加功能。要支持配置马上执行、要防抖节流两个结合起来、要均匀

  1. http缓存、强制缓存里面expire和cache-control作用,什么坑【描述】

重点题,频率很高。expire需要保证时间准确

  1. 前端路由实现。history什么坑,怎么解决【描述】

哈希和history,监听事件、切换元素。history会导致一些新路径404,nginx重定向到首页走js逻辑

  1. var、let、const区别,() => {} vs function () {}【描述】

基础送分题

  1. 一副扑克牌,随机抽 5 张,判断是否是顺子,大小王可以替代任意牌。【编程】

['A', '2', '3', 'S', 'B'] => true 先把AJQK映射成数字,然后把大小王S、B换成其他(我直接用symbol代替了)。排序去掉大小王的数组。遍历排序后数组,前一个数和后一个数字差距大于1,减少大小王数量来补。临界条件:前一个数和后一个数字差距大于1且大小王不够补,return false;成功遍历所有的元素,return true

(这里有点尴尬,忘记转数字类型了,很快写完了,但一直有问题,傻乎乎的debug,牛客网打印出来的结果也不知道是什么类型,都是黑色字。后面猜测是类型问题,typeof一看,哦果然是类型问题,加一个+号转数字,解决)

  1. ES5 实现 B 继承 A【编程】

为了表现,肯定是直接写寄生组合继承啦

2面面试官喜欢挖问题继续问,防抖节流硬生生写成了一个几十行的轮子了,不过我挺喜欢这种面试模式,临时造轮子改需求,随意天马行空地发挥,很好玩

3面

  1. 项目难点,画一下架构【举例】

临时给了一个在线文档地址,然后手绘了架构图

  1. 有了解其他权限系统吗,对比下【描述】

纠结了一阵我做的权限系统究竟是rbac几。前端控制、后端按需返回

  1. http请求的整个过程【描述】

经典题url到页面过程中的一部分——发请求到响应那段

  1. 怎么知道一个tcp请求数据已经完了呢【描述】

自己知道的,没有长度了

  1. 微博的@的下面出现一个提示怎么实现(pc上,类似群里讲话按下@,旁边有一个名字下拉框的那个功能)。不是editable喔,基于textarea怎么实现【伪代码】【描述】

一下子说了editable,他说你看看,他是textarea。接着有两种方式,隐藏元素+getboundingclientrect和canvas的mesuretext量长度。他后面说量长度不太行,而且很麻烦

  1. 怎么知道客户端是局域网下哪一个ip【描述】

客户端连接服务端的时候会携带自己的ip,服务器接收

  1. 为什么是tcp而不是udp。tcp丢包怎么办,怎么知道丢包,怎么知道已经重传成功了【描述】

TCP三次握手保证可靠性,而UDP就没有了,信息发出后,不验证是否到达,不可靠。丢包就重传。有seq,是连续的,如果收到的是不连续,说明中间缺了包;或者是超时了还没收到。因为有seq吧,所以多一个少一个也是知道的

  1. 了解http3的quic吗【描述】

udp快而不可靠,所以衍生quic。对比http2+tcp+tls,quic减少了tcp、tls握手,改进了拥塞控制,前向冗余纠错

  1. quic怎么解决了tcp的问题【描述】

使用udp作为基础,瞎讲一通拥塞控制、前向冗余纠错、bbr,所知道的概念都甩出去了

  1. quic用udp怎么保证了可靠性【描述】

用rudp来优化资源的占用率和响应时间,提高系统的并发能力。seq、超时重传、fec前向纠错

  1. quic的udp如果不握手,人家随便发请求怎么办【描述】

滑动窗口、bbr 拥塞算法

  1. 函数式编程、纯函数【描述】

先喘一口气,终于不问网络协议了。纯函数无副作用,同样的输入同样的输出。那我在里面定义变量和函数,里面做一些事情做一些修改这些变量的操作,还纯吗?一样的。

  1. 状态管理系统设计,怎么和函数式编程结合【描述】【举例】

常规react+redux项目举例

  1. rxjs介绍一下【描述】

以前玩过,异步流程控制,流、管道操作符概念

  1. 数组和链表的区别【描述】

数组易读取,链表只能一个个读或者需要额外空间才能易读取;数组增删元素需要照顾index,链表不用

  1. 数组和链表优点缺点,应用场景【举例】

数组增删的时候需要维护index,链表不需要考虑,但链表读取某一项就比较麻烦。很多情况下,简单的列表遍历用哪个都一样。数组的优势在于需要index的时候,随时读取某一个。链表可以模拟任何流程,并可以随时中断/继续,比如react的fiber使用链表可以随时回到当前状态

这是部门前端老大了,也是最难的一面了,被虐到狗血淋头。面试官人挺温柔的,前面的题答出来的时候也感觉很舒畅。后面各种被虐,因为不是科班出身,这些知识细节漏了太多,我只能尽自己所了解的都吐出去了,可能说了很多含含糊糊的、没有系统性的东西,知道什么和那个点相关的都讲了。我看见他在旁边笑了(感觉是"你还是太年轻了"的那种笑),忽然感觉局面很凉,第一次彻底的慌了,然后到了彻底的崩溃。回去我也默认自己三面挂了,也和朋友说我三面挂了,人家晚上还安慰了我一波。结果过了几天,说offer到了。。。

小结

遇到了本次出去社招最难一面,也充分暴露出野生前端的不足,计算机网络知识不系统,零零散散。这一块后面得补回来了

他们部门用的是ng全家桶,自动化测试也做得很到位。至于为什么用ng,他们老大说:“因为react生态太丰富了,我们做技术选型或者开发到后面会经常要考虑对比各种方案、要调研,不想花太多时间纠结生态,直接上ng一了百了”。这个理由,挺有道理的,我在我们团队也做过一些系统的前端架构设计、做过技术选型、带头做过升级react,也取得让我引以为傲的效果,但就没有往这个方面去思考过,面试官这个思考角度让我豁然开朗——原来事情可以这样思考。另外,现在ng的ivy也挺出彩的,大家有时间可以去了解一下

猿辅导是个很不错的公司,技术也挺强的,而且一般78点下班。还有,别忘了猿辅导是传说中开发实习生800一天的公司,除了这个,福利也挺多、挺到位的,员工关怀像腾讯一样到位

商汤科技

公司面试难度评估:✭✭✭✭✩

1面

  1. 看见你写的文章,还很深的,说一下这几篇【描述】

挺surprise的,居然有人那么用心看我文章,还看细节。于是带着兴奋的心情迫不及待和他介绍了

  1. react的class组件和函数组件有什么不同【描述】

class组件有生命周期有状态、函数组件就看返回值无状态(现在有hook了)

  1. class组件存在问题,函数组件的问题【举例】

又是经典问题,class组件随着项目变大生命周期逻辑过于耦合、庞大,函数组件可以更细粒。class组件需要走实例化流程,但可以使用装饰器。函数组件就不能使用装饰器了,函数组件ref需要forwardRef,不用纠结this。如果代码量都很多,函数组件可读性高一些

  1. class组件和函数组件diff、渲染、挂载过程差异【描述】

其实是一样的,最终结果有点不一样,可以看打包后代码

  1. em、px、rem【描述】

  2. rxjs在复杂异步管理的作用【举例】

没有在项目用过,他们那边是挺需要rxjs这种异步管理的,把流程视为时间轴,使用管道操作符操作异步数据流。一切异步流程你都可以画在弹珠图上清晰看见

  1. websocket和http协议区别【描述】

http无状态、被动;ws一次握手,知道状态,可以双向通信

  1. 完全不同的域名共享localstorage的方案【描述】

公共服务器双工通信(比较简单暴力)、嵌套iframe并双向通信(只要一个变了,马上通知另一方,保证他们的localstorage一模一样)

  1. 如果react项目要接入redux,每一步要怎么做【举例】

从api的使用到源码的实现。源码流程:provider传入store,connect要return一个组件,使用mapstatetoprops和mapdispatchtoprops扩展props,然后subscribe一下store,每次变化更新组件

  1. 对象、引用类型、immutable、...、Object.assign【描述】

放松一下,我们聊些简单的......

  1. 写一个你熟悉的吧,antd的tree渲染这个数据结构【伪代码】

在面试的页面上直接写jsx,高亮看得难受,也没代码提示。真的是放松题了,一个递归,tree包一下treenode,完事

一面还是挺轻松的,一种和人家交流技术的感觉。后面聊了很久他们的业务,做ai编程的,提交程序放到一个平台上跑,全程websocket双向通信,此时页面上有各种程序和图表,各种异步混杂起来,大概可以理解为什么用rxjs了

2面

  1. 项目深挖,反问一些问题【描述】

这里问了做数据mock的时候,如果有鉴权逻辑怎么办。可能有的人就马上动手了:做一个鉴权服务。其实不需要,你要清楚你的目的是什么,你只需要mock鉴权失败的时候返回的内容就行,到时候你可以随意切换mock数据

  1. settimeout(a, 3000); ...同步代码执行很久 settimeout(b, 1000)多少种情况,临界值【描述】【举例】

同步代码执行时间 <= 3000,顺序。> 3000先b再a

  1. 为什么会这样,说一下event loop【描述】

背书

  1. 浏览器底层对线程冲突的实现【描述】

不知道了。对方说因为有一个watcher,你可以看一下Chrome底层实现,比死记硬背宏任务微任务更好

  1. 一个页面,有图片、文字等各种内容,要求不能打乱排版和比例,如何兼容所有端【举例】

rem方案。但还是要看情况,一般情况下,手机是竖着的,电脑是横着的,总要对其中一个补白,不然很难看

  1. 浏览器缓存在spa的应用。html要不要缓存,为什么?其他资源呢,为什么【举例】

html不缓存,都是引用js,要保证最新。其他可以缓存,每次发布文件名都有md5保证不一样,而且也是增量部署的

  1. react性能优化【举例】

又是老问题了。scu生命周期、memo;usememo & usecallback记住一些值不用重新计算;虚拟列表;immutable+scu/memo;原生js;

  1. 100条香蕉,猴子离家50米,猴子每走一米要吃一根香蕉,猴子最大负重是50条香蕉。问猴子怎么做,可以做到拿回家香蕉最大化,最大可以拿到多少条回家【伪代码】

结果是啥不重要了,主要是思路。他问用dp还是贪心,我说都行吧,dp肯定是可以,贪心也算得上是。写了一段伪代码,在离家n米处有s条香蕉,每次选择回头或者前进,回头的话会损失2 * (50 - n) + 1,并补全到50条(库存能支持的情况下,相当于新增量减去损失量);选择前进,只会减少1。每一步选择最多剩余的,等于下一步的s值。临界点:离家0米,s就是答案; 离家50米,s就是50

2面是有一点挑战的,因为setimeout那道题,面试官建议我看一下浏览器底层和v8,这样子深入可以看到更多的东西。他说,只抱着一个mdn能学好前端吗?他们的业务是有做底层的,做直播+wasm的,技术还是挺牛逼的。国内做这方面的人也非常少。还有我问了一下如何通过wasm让浏览器支持h265,他说只要你看视频编码解码,加上wasm基础,一个月内就可以了,这些东西外行人觉得牛逼,其实只要你深入看一下浏览器底层一些东西,看一下Chrome底层是怎么运行的,就一目了然了。面试官在听我项目的时候,说我产品sense很好。因为在我的一些项目中,除了身为开发,还要做项目规划、定方案、架构设计,还要做一名技术产品经理提需求并争取一些人力。后面还聊了很多其他的,他最后还介绍了一些国外优秀的文档资源给我,可惜由于面试讨论得太兴奋,忘记加面试官微信了,有点亏

3面

  1. 项目深挖、提问【描述】

  2. 你项目怎么接入ci的,整个流水线是怎样【描述】

git提交 => lint执行 => 触发hook => 读取yml文件执行命令 => 部署 => 调用机器人接口发布企业微信群周知

  1. 设计一个短链接系统【描述】

页面链接映射 => 关键字符串 => 映射到时间戳 + 数字序号转高进制 => 获得短链接。第一次映射是为了满足多对一,第二次映射是一对一,进制转换为了简化字符串

应该是技术老大了,知识面很广,和他交流我只回答我懂的那些,他也没有刁难,专门找我熟悉的来问。最后再次重复了一下他们的业务,ai编程、提交到一个平台运行、异步数据流很复杂

小结

知道了需要学一下底层,可以看到一些事情的本质,也了解了一些冷门领域和其他领域的东西。技术还是玩得挺深的,可能比一些大厂的部门还要深

快手

公司面试难度评估:✭✭✭✩✩

1面

  1. react升到16,有什么坑需要解决【描述】
  2. 16后性能好多少,测过吗,你怎么测的。顺便问一下各种测速上报【描述】
  3. 为什么16的性能好,fiber流程是怎样的【描述】
  4. 为什么两个will生命周期要被标记为danger【描述】
  5. 用了react的哪些新特性,带来什么收益【举例】
  6. 浏览器http缓存那一套【描述】
  7. from memory cache、from dist cache什么区别,性能对比【描述】
  8. 根据什么而选from memory cache、from dist cache这两种缓存方案【描述】
  9. service worker怎么理解【举例】
  10. 输出一个字符串全排列【编程】

2面

  1. 项目深挖,反问一些问题【描述】【举例】
  2. react的setstate过程【描述】
  3. 说一下几种情况的setstate的输出,为什么【描述】
  4. react的合成事件【描述】
  5. 收到新state怎么更新,发生了什么事情【描述】
  6. ssr太久,你觉得什么原因导致【举例】
  7. ssr优化措施【举例】
  8. react的ssr和传统的模版引擎渲染对比【描述】
  9. ssr兜底容灾措施、降级措施【举例】
  10. 如何选择csr还是ssr,设计一套方案切换,让尽量多的用户得到最好的体验【举例】
  11. 有一个请求函数request,封装一下这个函数,使得多个相同的请求过来的时候不发请求,直接读取第一个的结果【编程】
  12. 有一个排序数组,返回第一个比目标数字小的数,要求log(n)【编程】

3面

4个砝码,一个天平,问能称出多少种重量(砝码可以两边都放,砝码重量自己随便定)【写出运算过程】

砝码重量自己随便定,就定一个理想化的情况,四个不一样的、且加起来也不存在重复的就行。如果你要考虑存在重量一样的两个砝码或者某些组合的和有相等的过程,那分类讨论够你折腾几个小时的。但面试只有20分钟,所以直接看理想状态的就行

小结

技术栈比较搭,基本用过的东西都是一模一样的。快手终面喜欢问智力题、数学题,之前校招也是终面问智力题,大家要准备一下一些经典智力题和数学题。如果排列组合、概率论这些基础忘了,建议回去补一下

最后

面试过程总结

自我介绍

稳定一套台词,介绍个人基本信息,做了什么业务和什么技术栈,言简意赅最好控制20秒内

问项目

自我介绍完了,一般就是介绍项目。有时候是默认自我介绍带项目详情,此时要看面试官是不是这个意思。时间不多,所以一定要讲一个具有代表性的、能最好的突出自己的项目

正式问题

熟悉的领域,一定要争取机会表现,而不是仅仅为了讲出答案。你甚至可以临时换位思考,这个人要怎么回答你才觉得他和其他人不一样。如果是自己不怎么会的不熟悉的,要根据表现来猜测过程,这个是靠积累的。面试比以前考试好多了,起码不会的可以靠猜,因为很多东西都是相通的、类似的。反正我多次都是猜的,回头查答案发现还是蒙对了

你有什么想问我的吗

首先问对方业务、技术栈、团队是必须的,你也可以放到二面去问也行。其次是可以当作一个和你闲聊的人,聊一下其他的事情,比如一些其他技术、为什么这样这样、公司方向、晋升、kpi、okr怎么定、考核之类的,或者加个微信。当然,必须根据对方性格来问,不能乱来讲、乱来问。要时刻记得一个事情,这个过程,除了面试之外,应该是要有一些其他收获的。如果这半小时甚至两三小时,你只有面试没有收获,那就亏了

hr面

如果hr还问你项目,技术方面的可以简单跳过。如果是问人生规划、为什么离职、怎么选择、怎么评价领导之类的,一定要说好话、说正能量的。背景都老实说吧,如果造假了,后面入职谁尴尬?背景调查查到了怎么办?你撒谎一句,那就需要再撒多几句慌来圆第一句。建议把自己想去的公司放最后去面,到时候问你你有其他offer吗,此时你就可以拿来抬价了。一般公司还会让你提供流水的,会根据上家的价和面试表现来定最终offer开多少价钱

鸡汤

只要一件事情能给你成长,无论过程,都是赚的了,最怕的就是一无所获,这样子只会浪费时间。看见不满意的、不好的,不要只看他不好的一面并无限吐槽,而是尽力挖掘它的价值,并吸收为自己的经验。我做的一些项目也是和大家一样,搬砖,普普通通,但我不希望普普通通,总会找机会搞点事情,尝试一下新的技术、新的方案、新的设计,并普及给团队其他小伙伴,这样子既能表现自己又能互利共赢。

无论做什么,不止前端,都应该要有自己的想法和思考,这样子才能把事情做好,做得更深。否则这就像一场梦,醒来还是很感动。希望各位读者,看上面的题目并不是背答案,而是理解它,并能活用,以后做类似的事情,有参考的思路。如果遇到和我同一个面试官,题目当然是不完全一样的,此时需要临场发挥自己的积累和灵活运用了。

最后再补充一点,如果你见过了普遍情况,了解到了普遍现象,那要是什么都和人家一样,最后不就是也成为普遍水平了吗?如果想脱离当前现状,实现突破,那么目标应该是成为有个性、有特色的、有区分度的人,成为一名不一样的前端,不一样的人。

全文花了比较长的时间,从规划到复盘、整理、输出,全是个人心血、真实经历,所以本文不转载,望谅解。关注公众号《不一样的前端》,以不一样的视角学习前端,快速成长,一起把玩最新的技术、探索各种黑科技