面试大厂反拷打指南(字节&腾讯)
最近面了字节(抖音支付)和腾讯(腾讯云)的前端实习岗:
字节三轮技术面全过,已OC;
腾讯三轮技术面全过,待约hr面。
目前没投其他公司,针对这六轮技术面做个总结分享。叠个buff(纯个人理解,不喜勿喷)
面试三大板块:八股、项目、手撕。
八股、项目、手撕占比的话,根据个人情况来定,如果你的项目特别亮眼,注重到了性能、稳定性、工程化,那么比例大致为3:5:2,反之如果你的项目没有特别引起面试官的兴趣,占比大致为5:2:3。
项目
首先说项目,每个人的项目都不同,针对项目这一点我只能建议如下:
如果你的项目用到了一些技术或组件库来优化,但是原理你自己都不懂,就不要往上写。那么怎么界定懂不懂呢?不是说你会copy一段代码过来,让这个跑起来了,感觉性能提升了,你就是懂。注意到我们这里提的是优化,在优化的前提下,你要知道你为什么用这个库,知道这个库的大致设计理念,前后对比你的项目有什么具体能量化到指标上的进步,更加分的点是你会实现这个库的简易版。比如你用到了懒加载,你起码要知道懒加载前后你首屏的请求量减少了多少,进阶一点就是懒加载用纯JS怎么实现,那如果你知道了用的是Intersection Observer API,你就要知道代码具体怎么写。再来个例子,就是Vue你用到了路由,那你就要知道路由用纯JS怎么实现,监听hashChange和History API两种方式的话,又怎么写代码呢?针对优化这两个字,你写上去的东西就是必须要经得起拷打!所以写上对项目的一些优化,是一件高风险高回报的事情。你对项目的理解很深,全能对答如流,会给面试官留下很好的印象,提升你的容错,就算后面的算法没有撕出来,也可能会让你过。如果你对项目一知半解,就是硬搬技术名词,修饰项目,会留下很差的印象,让面试官觉得你不懂装懂。我记得我以前在哪里看过这样一句话,面试很看开头的表现,很多时候前二十分钟面试官跟你聊下来后就知道你这个人大概的水平,后续可能只是简单的走下流程,顺便检验一下有没有看错。
八股
前端八股分为以下五个部分:
1. HTML+CSS
2. JS
3. 框架Vue或React
4. 计算机网络和操作系统
5. 浏览器
面试腾讯和字节这种大厂的话,HTML和CSS的占比会拉到极低,多出来的占比会分到计算机网络和项目上。至少本人在这六轮技术面,没有被问到任何HTML和CSS相关的八股,所以这里不讲HTML和CSS。
JS
为什么我要把JS单列一项不和HTML+CSS合并呢?因为JS的可考性确实太强了。一个V8引擎就可以拿出来讲很多。
V8引擎
1. 解析:代码→Token→AST(注意词法分析和语法分析两步)
2. 解释执行:Ignition解释代码为字节码,并收集热点代码
3. 编译器:TurboFan将热点代码优化转为机器码,并且在热点代码类型转变的时候反优化,这时候还涉及到隐藏类和内联缓存这两个知识,隐藏类就是相同结构的对象可以通过偏移量共享同一个隐藏类,内联缓存可以理解为隐藏类的加速器。
4. 堆和内存:进行内存管理和垃圾回收,垃圾回收分为新生代和老生代,新生代通过from - to算法把存活一次以上的移动到老生代,老生代通过标记清除配合并行回收和增量回收提升性能。
5. 栈:栈负责函数的上下文和参数帧分配。
JS异步
再讲JS的异步。简单一点的会考一些代码输出题,难一点的会让你讲原理,手写实现。比如Promise。Promise的手写是一定要会的,就算不会全部手写也一定要会写all, allSettled, any, race。再比如async await,它们是怎样让代码看起来像同步一样的?再比如setTimeout, setInterval。那就不得不提到JS的事件循环了,从Node.js 11+后Node.js的事件循环就向浏览器的事件循环对齐了,所以这里只讲浏览器的事件循环。分为微任务和宏任务,在script标签执行完以后,先执行微任务再执行宏任务。宏任务有script标签(JS整体代码)、setTimeout、setInterval、setImmediate、I/O、UI交互。微任务有Promise、process.nextTick(Node.js)、MutaionObserver。
闭包
还有闭包。闭包重要的是词法作用域,作用域链这两个概念,以及会牵扯到箭头函数,这个时候就引出了this指向代码输出题,进一步引出call, apply, bind,以及闭包的应用:函数柯里化,防抖节流。有趣的是腾讯云面试官复试时候问的最后一个问题就是假设我在跟产品经理介绍闭包,产品经理不懂任何技术。我说的答案是我买了一些牙刷,平常我自己知道这些牙刷我还想不想用,随时可以丢,但是有一个朋友来到我家里玩,用了一次牙刷后,我不确定我的朋友还会不会再来用牙刷,我就暂时会把牙刷留下来,直到朋友告诉我可以把牙刷丢了。现在想想如果我说的是家里的爸妈留着孩子的东西怕孩子回来还要用,可能会更感人哈哈。(可能两个故事对齐闭包都是错的,轻喷)
ES
再就是ES的各个版本了。ES5的严格模式、数组的reduce, map, filter方法、Json.stringify和Json.parse两个方法。ES6比较重要的默认参数、模版字符串、箭头函数、Promise、模块化、解构赋值,块级作用域、symbol等等。后面的ES版本就用年份来记录了,比较重要的是ES2017的async await和ES2020的可选链和空值合并。
TS
我也没用过,面试的时候都是说理解借鉴了Kotlin和Java,强类型,引入了枚举和接口等等,在底层编译还是会转为JS,主要是为了保证团队开发的代码结构以及规范性、严谨性。
框架
框架的话我主用的是Vue,所以只讲Vue。一般都是Vue2和Vue3对比着来讲。
性能
- Vue2 的虚拟 DOM 做的是全量 diff。
- Vue3 用到了静态提升、片段更新以及同层比较,优化了性能。
- 关于虚拟和原生 DOM 操作性能比较,需分情况说明:一般直接操作 DOM 更快,但在密集操作 DOM 情况下,虚拟 DOM 更快。原因是虚拟 DOM 最终要操作真实 DOM,环节更多,不过在密集操作时,它能将多次操作组合成几次,避免不必要操作。
响应式原理
- Vue2 通过数据劫持 API 劫持对象的属性来实现响应式,存在缺陷,即不能劫持新增加的属性,也监听不到属性的删除,并且由于重写数组方法实现劫持,数组索引也监听不到。
- Vue3 通过 Proxy 代理整个对象,解决了 Vue2 的上述缺陷。
ref 和 reactive
- 建议说自己用 ref。因为 ref 响应对象时调用的就是 reactive。
- ref 比起 reactive,唯一缺点是要多用.value 这一步,但后续语法逐渐同化,.value 也在逐渐被去掉。
API
Vue2选项式API,Vue3组合式API的区别,
生命周期及新组件
Vue的生命周期以及在Vue2和Vue3的差别,Vue的新组件suspense和teleport以及如何较少不必要的组件创建销毁,虚拟滚动优化长列表等等,感兴趣可以自己去Vue官方文档看看。
项目相关拓展
Vue还有一些Vue生态下的工具链会聊,大多数都是在你项目用到的前提下,比如用到了状态管理,就会聊Pinia和Vuex区别,作用等等。重点写了打包就会聊Webpack和Vite。这个时候就回到说项目时候给的建议了,不懂的千万别写!
简单聊下Vite,Vite分为开发环境和生产环境。开发环境下使用esbuild预构建依赖 + 基于ESM的按需编译,而Webpack需打包整个Bundle。生产环境下Vite用Rollup打包,和Webpack一样支持Tree Shaking,但配置更简洁。这里的Tree Shaking稍微展开讲讲,是在运行过程中静态分析模块之间的导入导出,删除未被其他模块使用的导出值。
计算机网络
计算机网络可以分七层网络模型或五层网络模型。就五层网络模型来讲,前端接触最多的肯定就是应用层和网络层。所以我们就只聊这两个的知识。
网络层
网络层就是TCP和UDP协议。首先要知道TCP和UDP的区别,一个面向连接注重可靠性,一个无连接注重性能。
TCP
就TCP的面向连接可靠性来切入,如何实现它的可靠性,是整个网络层最常考到的点。TCP的可靠性通过保证连接,保证包的顺序,保证不丢包这三个点来切入。第一个保证连接就是通过三次握手四次挥手实现,第二个保证包的顺序通过包体编号来实现,第三个不丢包通过重传机制来实现。理解了这个,WebSocket为什么要用TCP直接答因为其可靠性,HTTP3的QUIC如何实现UDP的可靠性的时候,照样从这TCP可靠性三个点切入就可以了。
UDP
主要是实现可靠性,看上一句话就行。
TCP粘包问题处理
三种方法,第一种特殊符号划分,比如1234%nsisdn%n通过%n划分,第二种固定长度发包,第三种包头存储包体长度。各自的局限性可以自己去深入了解一下。
应用层
应用层就是HTTP和HTTPS。
HTTP
主要有get、post、put、delete、options等。有时问到get和post区别,设计上来讲get要实现幂等性,post不提倡实现幂等性。options通常用于跨域请求作预检。重要的是HTTP1.0、1.1、2.0、3.0这四个版本,一定要讲清楚,讲出自己的理解。不知道有没有看过十日终焉的小伙伴,齐夏从燕知春那里学到可以通过记名词来轻松背下整个知识,背八股的时候很实用。比如HTTP1.0短连接,HTTP1.1长连接、缓存控制、断点重传,HTTP2.0头部压缩、二进制分帧、多路复用、服务器推送,HTTP3.0 QUIC解决多路复用。当你一个个去看完了这些名词对应的含义后,你通过背名词的方式就可以回忆整个知识了。
HTTPS
HTTPS和HTTP的区别可不是复数(bushi),HTTPS是HTTP经过SSL或TLS四次握手生产对称密钥进行加密通信,四次握手的过程可以去b站看下小白debug主页,短视频的方式,讲的很有趣且生动。
其他
拥塞控制和流量控制
拥塞控制是对整个外部网络环境进行判断,避免发送到网络中的数据过多,通过四个算法:慢启动,拥塞避免,快恢复,快重传实现。流量控制是点对点,避免设备之间发送和接收能力不对等,通过滑动窗口来对齐设备之间的接收能力。
常见的状态码
2开代表成功,3开代表重定向或者缓存控制,4开代表客户端错误,5开代表服务端错误,常见的是200、301、302、304、400、401、403、404、500。
浏览器
浏览器的知识主要分为渲染和缓存控制以及跨域处理:
渲染
渲染就是问的比较多的输入一个url到显示有什么流程。考这个的目的是针对整个浏览器渲染的流程可以做很多事,比如针对网络层面,HTTP做优化,针对渲染的重绘重排做优化等等。还需要注意的是DNS解析可以说的细一点,会提升一点好感度,比如经过根域名服务器、顶级域名服务器、权威域名服务器这三层DNS域名服务器,获取到IP地址。
缓存控制
缓存控制就是协商缓存和强缓存,请求头的优先级是cache-control>expires>If-none-match>if-since-modified,前两个请求头来自强缓存,后两个来自协商缓存,所以优先使用强缓存,强缓存失效使用协商缓存并且if-none-match对应响应头e-Tag,if-since-modified对应响应头last-modified,last-modified优先级较低的原因是时间作为标识的话容易对一些同时更新的缓存造成误判。而e-Tag作为唯一标识优先级自然就要高。总体流程就是访问强缓存,成功返回200状态码,缓存过期则协商缓存,协商缓存没过期则返回200状态码,过期了则返回新缓存并返回状态码304。
跨域
跨域一般就是后端配置就好了,get请求可以通过JSONP实现,当然也可以自己弄个服务器作转发,想理解的更深自己解决一下就知道了。
手撕
手撕的话纯靠自己努力,我动态规划刷的多一些。
总结
有的同学就问了,篓哥篓哥,你的打法还是太吃操作了,有没有更加简单又强势的方法呢?没有的兄弟,没有,一分耕耘一分收获
。差不多就讲完了,纯手打一坤小时思路没停,可能会有遗漏或错误,遗漏就是我忘了,后续会补上,错误就是我理解有问题,会及时纠正。制作不易,喜欢的可以点个赞收藏一下,也可以关注我,后续我会深入分享某些技术。祝各位彦祖亦菲们都能不负自己的努力,拿到自己心仪的offer!
介绍面试大厂过程中各种有可能被拷打的点,并且通过从思维层面上的讲解,根本帮助读者们改变面试思维,助推读者实现反拷打。