如果生活存在奇迹,那一定是努力的轨迹!
Hello,大家好,我是小羽同学,一个平凡而又不甘于平凡的前端开发工程师。
emmm,今天呢,主要就想和大家聊聊小羽同学的 CVTE突袭面经 吧~
为啥说是 突袭面经 捏?
嗯,就是突如其来,毫无还手之力的面试邀请。
收到面试邀请时,我TM才刚开始复习两天!!!
本来是准备3月底/4月初让呆呆帮忙内推的。。。
后面让呆呆大佬帮我查了下记录,年前就进入人才库了!没啥印象了呀,大人我冤枉啊!
还好呆呆说我挂了的话,还可以把我捞起来(继续鞭尸),然后我就豁出去了,冲啊_φ( °-°)/
先简单的说一下个人的基本情况吧
【基本信息】
- 19年6月毕业,
计算机科学与技术,渣本 - 工作经验
一年半,实际工作年限2年(因为大厂的工作经验是从毕业时间算起的) - 技术栈:
vue全家桶系列、nodejs、nginx、CI/CD、docker - 目标:广州一线大厂的前端开发岗位
【优势】
- 科班出身
- 搭建了公司项目的前端框架
- 参与并解决过公司项目的
前端性能调优问题 - 担任过
面试官,对面试的题目有一个整体性的了解 - 开源项目《小羽直播平台》
- 开源项目 SULG UI组件库
【劣势】
- 技术栈是vue(目标是大厂,而大厂一般都是react)
- 一年半经验,两次跳槽(现在是第二次,原因都是想进一线大厂,可惜第一次连大厂的面试机会都没能捞到)
- github的星星量较少(小伙伴们可以帮下忙吗?)
小羽有过前端面试官的经历,也面试过不少的人选了,所以也说一下作为面试官,对人选的感觉吧。小羽把人选总结了一下,大概可以分为以下三类
【不够自信】
这类小伙伴给人的感觉就是有一定的技术,但面试的时候比较紧张,导致说话结巴或者对技术的描述断断续续的,然后给面试官的感觉就是人选不够自信,对技术的掌握程度不高,然后会拉低面试的评价。所以建议感觉建议这类小伙伴可以在复习时,模拟面试的场景用自己的语言组织答案。如果时因为紧张的原因导致的,可以先去一些非目标公司练下手,热下身,主要还是要克服自己的心理。
ps:小羽在面CVTE前也想去热身的,可是条件不允许了,啊啊啊啊啊啊啊啊 (╯°Д°)╯︵┻━┻
【过于自信】
这类小伙伴怎么说呢,可能就是对自己的认知不够深刻。觉得面试官问的所有问题自己必须能答得上来(当然能全部都答上就再好不过了)。emmm,怎么说好捏。其实面试的时候不是必须要全部都答上,有个一两道不懂是挺正常的。碰到自己没复习或者感觉了解不够深的地方,可以直接说没怎么了解过,面试官不会因为这么两道题就给你直接挂掉。如果你觉得自己能答上,但是了解的不够深,就会被面试官刨根问底的开虐了。
ps:小羽在CVTE技术二面的时候,不小心就陷入这个局面,反正多多少少算是个减分项吧 o(╥﹏╥)o
【自信、阳光】
这类小伙伴是最有机会通过面试滴。他们通常会做比较多的准备,面试的时候给小羽的第一感觉就是阳光自信。给人的感觉就特别的棒,有想让他们加入自己的团队的想法。这类小伙伴基础一般都比较扎实,然后会在简历、自我介绍、项目描述等多个维度,会有意无意的把面试官往自己最擅长的领域去引,然后就感觉像是在做一场技术交流而不是面试,所以这类小伙伴通过的几率是最大滴。
一般来说,一轮技术面的时间是30-60min,当超过60min后,面试官就算还有想问的东西,他也会尽快的把这场面试结束掉,所以小伙伴们,在自己熟悉的领域能多说就尽量多说点哦~。然后面试官也是没有挖掘你的特点的义务的,就像刚刚介绍那类阳光自信的小伙子,他们就会从各种维度把面试官引入自己熟悉的领域,然后展示自己的优点,尽量多说点。面试其实就是在展示自己的优点,如果在自己熟悉的领域都不能折服面试官了,其他层面就更不用说了。
嗯,基本信息和面试官的一些感想聊完了,就开始聊聊小羽同学这段梦幻般的复习和面试经历吧
在收到CVTE的突袭邀请后,复习了两天就开始面试了。复习的这段时间,基本每天早上6点就强忍着倦意起来了刷api手写系列和leetcode(原来都是9点起床洗刷,然后晃悠晃悠的走去公司的)。每天下班后,都是快速解决晚饭,然后就疯狂恶补梁哥的【求职系列】。在这里先感谢一下梁哥的总结,没这份总结,小羽无论再怎么抱佛脚,也是没办法将那些纵横错落的知识点拼凑成一条完整的知识链。
给大家介绍一下我的外挂,额,最强应援团!!!
CVTE 技术一面(电话面 50min)
面试官是一个小哥哥,没有自我介绍,直接开始面试了,这是想说:要不快点开始吧?我已经迫不及待的想吊打你了,自我介绍那种东西就不需要了。【囧】
1.var let const 区别 变量提升 堆内存 栈内存(大概问到了这些知识点)
var 有变量提升,而let 和 const 是块级作用域
var和let都可以先声明不赋值,const必须要赋值,否则会报错
js中有基本数据类型和引用数据类型
基本数据类型存储于栈内存(存值),引用数据类型存在堆内存中(存地址)
而const定义的是一个常量,如果定义的是一个基本数据类型是不能改变的。如果定义的是一个引用数据类型,那么引用数据类型中的数据是可以改发生改变的,因为堆存的是地址,即地址无法改变。
2.cookie localStorage sessionStorage 区别以及使用场景
【相同点】
- 都属于本地缓存
【不同点】
- 大小:cookie 4k左右,localStroage、sessionStorage一般是5M(IE是3M左右)
- 通信:cookie每次都会携带在请求头中,localStroage、sessionStorage不会参与和服务器的通信
- 失效时间:cookie一般是浏览器关闭就失效了(可以设置expire来改变失效时间),localStorage不删除都会有效,sessionStorage则是在tab标签关闭后就失效了
【使用场景】token,然后就引出了下面的单点登录和token
3.单点登录和token、系统权限
面试官:你们公司的单点登录系统是怎么实现的,token又是什么?系统权限你们又是怎么实现的?
我:吧啦吧啦。。。
4.http 2.0、域名发散、域名收敛
- 使用hpack算法,进行头部压缩
- 支持二进制传输,http1.x是字符串传输
- 多路复用(中间面试官拓展的问了一下域名发散和域名收敛相关的问题)
- 服务器推送
5.flex布局
emmm,这个忘记问了啥,尴尬。。。
6.性能优化
面试官小哥哥:看你在项目中有做过性能优化,能分享一下吗?
我:巴拉巴拉。。。
7.虚拟列表
从性能优化中引出来的
主要就是用来优化长列表的(当无法使用分页时)
通过计算,仅渲染可视化窗口部分。
8.nodejs
面试官小哥哥:有用过nodejs吗?做过一些什么呢?
我:我学习nodejs主要是为了能够更深的了解前后端的交互,写过一些简单的的后台和爬虫
面试官小哥哥:有写过中间件吗?
我:没有
然后就没问了
9.webpack、loader、plugin
关于webpack系列的,首推ENOW大前端团队的《当面试官问Webpack的时候他想知道什么》
10.项目问题
略
电话一面不难,大部分都是基础+项目问题。像小羽这么菜的人都过了,小伙伴们准备一下应该都问题不大,加油哟~
第一轮技术面试和第二轮技术面试间拖了一周左右的一个时间,终于可以让我从头到尾把梁哥的求职系列看了一遍(除了react,还好CVTE可以接受vue转react)。其实小羽在技术二面时leetcode刷的并不多,从复习开始一天5-7道,简单题大概刷了60道左右吧,主要是科班出身,有一丢丢算法基础。这也算是尽了最大的努力了,毕竟时间实在是太紧了!!!
CVTE hr一面(视频面 40min)
但我没想到接下来的是hr面(大概两天后),我还以为是技术面,又是一个措手不及!!!
- 个人的一些基本情况
- 跳槽原因
- 薪资情况
- 期望薪资
- 个人规划
- 家庭情况
- 工作中的相关情况
- 技术二面的时间
CVTE 技术二面(视频面 70min)
本来是想约现场面试的,顺便和呆呆面基的,哈哈哈
但是后面因为某些情况,又改回了视频面
1.自我介绍
略
2.工作内容,怎么领导新员工
略
3.SULG UI开源组件库
怎么和朋友分工的?
怎么设计组件的?
遇到什么难点?
4.项目难点,你是怎么搭建架构的
主要有单页面应用改多页面应用和性能调优两块吧
然后,开始吧啦吧啦
5.有了解过微前端嘛,为啥单页面应用改多页面时不考虑微前端呢?
有看过阿里的qiankun(路由分发式微前端),自己也有写过相关的Demo
但是微前端对于团队的整体能力要求会比多页面应用高一点,而我们的项目都是统一的vue,大家都会使用的,不存在vue、react、angular、jquery等多种技术栈混合在一起的,所以暂时没有改成微前端的必要。
6.http缓存
强缓存、协商缓存、启发式缓存
【强缓存】
强缓存是利用 http 头中的
Expires和Cache-Control两个字段来控制的。强缓存中,当请求再次发出时,浏览器会根据其中的expires和cache-control判断目标资源是否“命中”强缓存,若命中则直接从缓存中获取资源,不会再与服务端发生通信。
expires是一个时间戳,二次请求我们试图向服务器请求资源,浏览器就会先对比本地时间和expires的时间戳,如果本地时间小于expires设定的过期时间,那么就直接去缓存中取这个资源。它最大的问题在于对“本地时间”有很大的依赖。如果服务端和客户端的时间设置可能不同,或者我直接手动去把客户端的时间改掉,那么
expires将无法达到我们的预期。所以我们有第二种方法Cache-Control。
Cache-Control是一个时间长度,我们通过max-age来控制资源的有效期,它意味着该资源在时间长度以内都是有效的,完美地规避了时间戳带来的潜在问题。它的优先级更高,当两者同时出现的时候我们以Cache-Control为准。【协商缓存】
协商缓存依赖于服务端与浏览器之间的通信。协商缓存机制下,浏览器需要向服务器去询问缓存的相关信息,进而判断是重新发起请求、下载完整的响应,还是从本地获取缓存的资源。如果服务端提示缓存资源未改动(Not Modified),资源会被重定向到浏览器缓存,对应状态码是304。
【启发式缓存】
如果响应中未显示
Expires,Cache-Control:max-age或Cache-Control:s-maxage,并且响应中不包含其他有关缓存的限制,缓存可以使用启发式方法计算新鲜度寿命。通常会根据响应头中的2个时间字段Date减去Last-Modified值的 10% 作为缓存时间。
7.http1.0/1.1/2.0/3.0
这个直接参考梁哥的【jsliang 求职系列 - 29 - HTTP/HTTPS】就可以了~
8.宏任务与微任务
给了一道题,说了一下输出的先后顺序。然后又扯了一下even loop
宏任务(macrotask) 和 微任务(microtask) 表示异步任务的两种分类。
1.一开始整个脚本
script作为一个宏任务执行2.执行过程中,同步代码 直接执行,宏任务 进入宏任务队列,微任务 进入微任务队列。
3.当前宏任务执行完出队,检查微任务列表,有则依次执行,直到全部执行完毕。
4.执行浏览器
UI线程的渲染工作。5.检查是否有
Web Worker任务,有则执行。6.执行完本轮的宏任务,回到步骤 2,依次循环,直到宏任务和微任务队列为空。
9.算法题(暴力递归)
给定一系列的任务,这些任务可能有依赖关系,有依赖关系须相继执行,没有依赖关系则可以同时执行。 写一个函数,计算完成给定所有任务需要的时间。
//例如下面这些任务执行总时间为 4 const tasks = [ { "name": "task1", "time": 1, "dependency": "", }, { "name": "task2", "time": 2, "dependency": "", }, { "name": "task3", "time": 3, "dependency": "task1" }, ];
function getTime(tasks){
let taskObj = {},max = 0
for(let item of tasks){
taskObj[item.name] = item
}
for(let item of tasks){
let currentMax = item.time
if(item.dependency){
currentMax += dep(taskObj[item.dependency],taskObj)
}
if(currentMax > max){
max = currentMax
}
}
return max
}
function dep(task,taskObj){
if(task.dependency){
return task.time+dep(taskObj[task.dependency],taskObj)
}else{
return task.time
}
}
10.链式调用
还没复习到链式调用,小羽答得非常糟糕,以至于一度以为自己挂掉了。
关于链式调用,小伙伴们可以去搜一下lazyMan那个题就好了(CVTE不是lazyMan,但思路是一样的)
CVTE hr二面(视频面 40min)
由于cvte技术二面的链式调用答得非常糟糕,快三天没收到电话,以为自己挂在了技术二面了,没想到电话它突然响起来了!!!
- 跳槽原因
- 对新公司顾虑的地方
- 前端未来的发展趋势
- 目前工作的作息时间
- 下班后会做些什么
- 压力大的一段时间
- 公司技术部的情况
- 个人能力在公司的排行
- 大学期间的学习状况
- 个人未来3-5-10年的事业和生活的规划
- 假如说未来工作和事业没能达到你的期望,你会怎么办?
- 你想进大厂的原因
- 如果有其他更好的公司,你会怎么抉择
- 个人的兴趣爱好
- 对你个人影响比较大的事或者人
- 还有什么想问吗?
emmm,面完hr二面后。大概2-3天就收到了口头offer,突然觉得挺对不起呆呆的,因为我把他的内推奖励给弄丢了。
CVTE 希沃加面(视频面 60min)
emmm,本来hr二面后已经拿到口头offer了,因为某些特殊原因加面了希沃(偷偷甩个锅给呆呆,是他在微信视频号里面点了个赞,然后我“万恶”的好奇心,一个不小心点了进去。嗯,然后我就被希沃吸粉了)。
1.自我介绍
2.性能调优
以下全是由性能调优开始扩展开来
v-for添加key值,然后扯了下diff算法、以及如何确定性能是否有提升
v-if和v-show的合理使用
v-once渲染只需要渲染一次的元素
合理的使用生命周期,使用场景
合理的使用computed和watch,使用场景以及二者之间的区别
过滤api接口的数据,object.freeze()(引出vue的数据劫持原理,为什么要过滤掉没用的数据)
图片懒加载,路由懒加载(引出:100个http请求,http1.0/1.1/2.0需要建立多少个链接,为什么?然后又问了http相关的一些问题)
cdn,什么样的文件适合放cdn(引出http缓存),如果需要更新cdn怎么办
nginx调优
还有什么想问的?
中间插入一道简单的算法题(有点紧张,一开始没注意到空格,大佬给了点提示才写出来,递归)
// 以下是单元测试
const test = () => { const listArray = [
{ input: [1, 2, [3, 4, 5]], output: '[ 1 2 [ 3 4 5 ] ]', }, { input: [79, [[88, 98], 99]], output: '[ 79 [ [ 88 98 ] 99 ] ]', },]
listArray.map(data => {
const result = stringify(data.input) console.log(result === data.output)}) }
test();
const stringify = (list,res="") => {
// 这个函数用来把数组扁平化为字符串, 格式见示例
// 输入的数组只包含数组和数字两种类型复合
res += "[ "
for(let item of list){
if(Array.isArray(item)){
res+=`${stringify(item)} `
}else{
res += `${item} `
}
}
res += "]"
console.log(res)
return res
}
希沃加面完后,和呆呆打了个视频电话,呆呆告诉我这是他老大,然后在电话中也聊了不少其他的东西。比如说我一个不小心就从呆呆的小本本上溜了出来,反正主要聊得都是我一段快可以写成小说的梦幻般经历吧,哈哈哈。
ps:小伙伴们可以猜一下呆呆会干嘛,反正不管你们猜没猜中我都不会告诉你们滴~【狗头】
希望我的CVTE突袭面经能给小伙伴们带来一定帮助和启发,嘿嘿
如果有梦想就不要轻易放弃,相信自己也是可以的,欧力给!!!
在最后,再次感谢我的应援团(外挂团)的两位大佬,呆呆和梁哥。顺便求一波关注,爱你们哟~