年后被吊打的第一面

225,543

背景

base重庆,面试中高级,目标先检验一下自己的水平和能力顺便看看薪资,好直接开始把。

自我介绍

讲了一下自己的技术栈:掌握vue全家桶,底层及上层框架、掌握react底层原理、熟悉js、熟悉工程化、熟悉微信小程序、使用过node、关注前端趋势有开源经历、主方向工程化等。

大概说了1分钟把,可能是我一边自我介绍一边在笑,面试官就问了一下:“你看起来心态很好啊!你是不是要写面经啊?”

我:“我是紧张才笑,应该是可以吗?要不多问点把~”

面试官:“可以,行”

记住这句话,我现在很后悔

步入正题

面试官:"那我们先来点基础把",下面都是我原话,小伙伴们可以纠正一下。

JS浏览器基础篇

1、dom树是怎么生成的

"浏览器是多进程架构,而其中有一个渲染进程,负责页面的渲染和js脚本的执行,而在渲染进程中有一个HTML解析器,oh对还有一个网络进程,网络进程负责根据content-type创建渲染进程,然后渲染进程用类似stream流管道那种接字节流将它解析为dom"

“而解析时,我觉得可以对标现在的各种转移编译工具,都有一个词法分析、语法分析、transfrom、genoretor的流程”

“你能具体说说这个过程吗?”

“(心理活动:当时脑子就蒙了、有点超纲啊、我要不猜一下)稍等我想一下、跟babel应该很像吧、会对一些声明命令赋值注释分词,这块我不是很了解,但应该对于html分词就是分的标签和文本内容,然后再通过算法去转换成dom”

“行,你上面提到了分析器,那如果当分析器遇到了script标签那”

“(心理活动:......这八股文味不对劲啊),我不知道对不对,但表现的是当遇到了scrpit会暂停html转换dom,去解析jascript,而async和defer会异步加载不会阻塞html转换”。

2、渲染进程

还可以你可以自信点虽然有些地方不是很对,但已经够用了。刚听你说了渲染进程,你说说它下面的几个线程把。

“emmm,下面的主线程吗,有主线程、GUI渲染线程、事件触发线程、定时器触发线程(后面发现漏了一个http线程),em,主线程和GUI是互斥的、js执行太长会造成页面渲染卡顿,但现在有很多解决方案,比如:在react中的调度器预留的5ms空闲时间、web worker之类的。然后是事件触发线程和定时器线程都是在任务队列去做Loop”

“行,那事件循坏我就不问你了,问问你V8的垃圾回收把”

“(你问啊!你问啊!)”

3、v8垃圾回收

“首先js因为是单线程,垃圾回收会占用主线程,导致页面卡顿,所以需要一个算法或者说策略,而v8采用的是分代式回收,而垃圾回收在堆中分成了很多部分用作不同的作用(我在说什么啊!当时),回收主要表现在新老生代上,新生代就活得短一点的对象,老生代就活得长一点的对象。

“在新生代里有一个算法,将新生代分成了两个区,一个FORM,一个TO,每次经过Scavenge会将FORM区中的没引用的销毁,然后活着的TO区调换位置,反复如此,当经过一次acavange后就会晋升的老生代还有个条件就是TO区的内存超过多少了也会晋升。”

“而老生代,采用标记清除和标记整理,但标记清除会造成内存不连续,所以会有标记整理取解决掉内存碎片,就是清理掉边界碎片”

“为什么TO超过25%要晋升老生代?标记清除是怎么清除的?”

“不知道~”

“第一个问题是为了不影响后续FORM空间的分配,第二个问题你应该看过有关这方面的文章把,垃圾回收会构建一个根列表,从根节点去访问那些变量,可访问到位活动,不可就是垃圾”

4、浏览器缓存

就强制缓存,协商缓存,浏览器内存那些,有兴趣看看文章,讲细点就行。写着太累了,当时讲了一大滩,直接说面试官问题把。

“因为提到了这些缓存,你觉得他们对于我们实际的业务场景下怎么运用”

“(蒙蔽),很大一部分是浏览器优化,一些http缓存我们可以做一些控制,本质上我感觉这些都属于性能优化的部分。”

“行”

5、JS上下文执行栈和闭包

“几个概念把,esc、上下文:作用域链,AO/VO,this。esc存储执行的上下文”

“算了我以一个函数来说把,主要是创建和执行。假设有一个A函数,过程是这样的创建全局执行上下文、压入esc、全局上下文初始化、执行A函数、创建A函数执行上下文,压入esc,A函数上下文初始化,这个初始化过程是这样的:创建作用域链、emm我上面提漏了一个A函数被创建全局上下文被保存到scope中的过程,是复制scpoe创建作用域链,用arguments创建活动对象,初始化活动对于,将活动对象压入链顶,执行完毕,上下文弹出。”

“但是全局上下文一直在栈底,而VO和AO的确认,我感觉是取决是是否可访问的。”

“而闭包就是上下文链中上下文scope被销毁了,但因为保持了对scope中某个变量的引用,这应该就是你上面说的回收原理的根节点实现的这个东西把,导致没销毁干净,留存在了内存中,完成了闭包”

“你怎么看待闭包的副作用”

“emmm,其实我觉得闭包是语言特性,虽然有副作用但我觉得其实挺好的,但只要管理好它就好了。况且又不是只有闭包会造成这些问题,就比如:react里面还有专门去清理一些链表和难回收的东西,去帮助v8回收。我觉得这得取决于写代码的人。”

“可以的,我感觉你的基础还是挺好的,你说下es6的东西把,控制下时间”

“你想听哪方面的那?因为东西太多了”

“工程化把,因为我前面听你介绍主方向是工程化”

“(...我怎么感觉工程化相关的只有一个esm模块化啊,这个怎么分类啊)esm:异步加载、引入抛出,编译时,值的引用。大概就这些东西把,其他的不知道了”

“行”

“那您觉得还有哪些那”

“就比如:Promise和async之类的啊”

“(..................)”

“来手写几道题把”

6、bind pipe compose 深拷贝

这个网上太多了,大伙自己去看。

CSS基础篇

“我可能CSS有点烂,但基础的应该都知道”

“先说说BFC把”

1、BFC

“BFC给我的感觉就像是个封闭盒子,不会在布局上影响到外面的元素。平常会触发BFC比较多的就是body,浮动元素、绝对定位、flex、overflow之类的。在BFC可以清除浮动、阻止元素被浮动环绕之类的。(然后我一边说一边尴尬的笑)”

“大概知道你CSS是个啥水平了,简单问点把,你说BFC可以清除浮动吗?为什么?”

“不知道”

“其实准确的说不是清除,是因为浮动元素也是BFC,两个BFC互不影响。你提到了BODY触发BFC?”

“emmm,可能是也许不是BODY,是HTML根元素”

“是的,不是BODY”

2、居中

"flex布局,positon,flex margin:auto,position transform,table-cell"

"行了,层叠上下文和层叠顺序"

3、层叠上下文

“(.......这时候感觉每多问我一个CSS都是煎熬啊),em我其实一般对于会遇到有层叠上下文不清晰的情况都是指定z-index.”

“行”

4、flex布局

“这样吧,你平时用得比较多的是什么布局?”

“flex布局把”

“那我们来聊一下flex布局把”

“(拜托我真的会哭,我感觉面试官他好兴奋),emmmm,我觉得布局无非是控制内部元素和控制容器,而flex布局对于容器的控制是基于轴这个概念的,而flex中的轴分为:主轴、垂直轴、换行轴。”

“主轴指的就是元素排列的方向轴,而flex-direction是最重要的属性在主轴中,row和col控制角度,reverse控制方向,但我们其实平时用得比较多的就默认的row和column,column会把元素垂直去排列。而主轴的另一个属性justify-content是控制元素在轴上的排列,然后我说了一下常用的几种就start end center between around”

“垂直轴就是垂直于主轴的方向轴~然后我停了大概有20秒(又开始笑了)”

“没了?”

“(啊啊啊啊啊!)可能就我只知道align-items控制垂直轴上的位置,然后说了下,start end center。”

“还有换行轴那”

“嗷对,就是刚才提漏了,垂直轴是针对于当前行,但换行轴是针对于整个容器。”

“这个针对怎么说?你继续说换行轴属性。”

就是高度嘛,布局换行后,垂直轴的高度只会是当前行高度。flex-wrap,但我只用过wrap,emm对于控制内部容器我了解得很粗浅。

"你可以了解一下wrap-reverse,下来可以去看一下正负剩余空间和flex-grow flex-shrink这些"

“抢答!就是flex:1这种写法的哈”

“对的,你知道吗”

“不知道”

我们两个同时沉默了(啊!!!!!!!!)。

"没事其实比我想象得稍微好一点,至少你在你不擅长的东西上也是花了时间去学的,css就不问了,下面问点框架把"

“谢谢!谢谢!谢谢!”

框架基础篇

“你简历里是React和Vue都会,那先说说你是怎么看这两个框架的把”

1、对React和Vue的看法

“在开发模式上,React发明了JSX这种开发模式,并且用了很多年时间让社区去接受,而Vue则是采用现成的模版语法的开发模式。但感觉就这两年这两个框架都在往一个函数式组件的方向靠,不应该说靠是已经实现了,Vue3中的函数式组件甚至在某种层面上说比react更自由。当然洛现在声明式的编程是主流嘛”

“在实现层面上说的话,就那一套,单向数据流,双向绑定,数据不可变性,更智能的依赖收集,优化的方式不同等”

“听到你说了更自由和智能的依赖收集,具体指的是?”

"比如react useEffect要手动加依赖,但vue3的wachEffect和computed就不用"。

“自由,em就比如,hook得顶层,不要条件循坏用,而且react重心智负担:就闭包陷阱那一套过时变量嘛,依赖的选择,还有重复渲染这些问题,我一直不理解为什么不把这些心智负担收到框架里,我觉得react是有这个能力的。vue3的话,你想咋用咋样api咋样,setup也会只用一次,也不会像新旧树对比hook多次调用”

“哈哈感觉你对react怨气好大,因为我看你文章写了很多react源码的嘛,如果是你你会怎么去收敛这个心智负担到框架内部?”

(.......绷不住了啊,吹过头了),稍等想1分钟,就是hook顶层那个和条件循坏应该不好动,因为react不能去破坏hooks链表的结构,对于过时变量react18已经将usestate全改为异步了,依赖的选择的心智问题我觉得是否说可以更明确一点再未来加入配置项的话,将依赖的收集在updateEffect和mountedEffect前去提前收集,就做一个依赖系统专门去处理这个事情,感觉可以从编译器自动生成依赖数组,现在react只是一层浅比较。但其实这么想,大部分问题的根源,是React函数组件机制所限:每次组件渲染,组件里的所有代码都会被重新调用一次,在这上面其实也可以动下手(自己说了感觉当没说,感觉好尴尬啊硬吹)。就长话短说就是,react的心智模型让我要花很多精力去处理边界情况。

“其实你最后句话说得挺好的,因为react要求你用声明式的方式去写组件,你就不该去纠结引用会不会变,多添加个依赖很不舒服,重新渲染这种事情,你需要保证的是无论重新渲染多少次这个组件都不会变。假设你useEffect依赖于AB,但你的B就可能只在首次创建后永远不变,它确实显得很“多余”但你不用纠结这个。真正的问题可能就在于你觉得的永远不会变只是你觉得,我们平时出现问题很多都是这种以为的边界问题导致B变造成的”

2、为什么react需要合成事件

“兼容性的考虑把,可以抹平不同浏览器事件对象差异,还有个就是避免了垃圾回收。”

“我们公司主要是Vue,你的简历里Vue也更擅长一些,我们谈一下Vue把”

3、生命周期

随便了一下,每个生命周期,父子生命周期,每个生命周期的定义和写法。

4、路由

5、指令

6、响应式原理

7、数组处理

8、key,diff算法

9、V3组合式API

10、一些TS系统

11、V3编译原理

“上面也问了挺多的了,你讲讲Vue3里面的模版编译和函数式组件编译把。”

“(我崩不住了,妈妈我想回家)先巴拉巴拉扯了一下pnpm和menorepo和整体v3源码,然后讲到complier,同样vue模版的编译也是通俗流程就是parse transform gen,我没具体研究过,但parse应该也是对标签属性文本指令等一系列做处理去干成AST,然后transform做转换最后生成。”

“行上午先面到这,二面通知你,有什么要问的吗?”

“em,你觉得我咋样(我好直白~)”

“挺不错的,2年经验,感觉你知识的掌握程度大于你的年限,有点好奇平时你怎么安排学习时间的”

“就可能目前这家公司比较清闲把,再加上学习写代码对我比较快乐,就能投入很多时间和精力,哎,就二面能不能快点!可以加个微信吗~”

“行”

总结

然后二面就是项目面了,啊好累啊,现在前端真卷啊,其实感觉可以多问点工程化,虽然准备了很多但是没被问上。

emmm,因为看评论区嘛,就想说,乐观点,其实也没这么卷,只要自己多写写代码和看看八股文都可以的,当然最重要的还是思考。emm想加群一起卷的可以看沸点