FE 随手记
JS浏览器基础篇
建议根据《JavaScript高级程序设计》进行系统学习。
基础知识超高频考点有数据类型以及判断方法、闭包、块级作用域、函数提升与变量提升、原型链、JS继承、变量深浅拷贝等等
JS 高级特性:闭包将涉及到内存泄漏问题与垃圾回收机制
JS是单线程的语言,浏览器和Node.js定义了各自的Event Loop(事件循环机制)则是用来解决异步问题。将程序分为“主线程(执行栈)”与“Event Loop线程”,“主线程”自上而下依次执行同步任务,“Event Loop线程”将异步任务推入宏任务队列与微任务队列去执行,在下面这段代码是面试中关于这类问题的经典考题,其中包含了同步、异步任务,几个输出的先后顺序是怎样的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16setTimeout(function(){
console.log('1')
});
new Promise(function(resolve){
console.log('2');
resolve();
}).then(function(){
console.log('3')
});
console.log('4');
// 2,4,3,1
// 首先进行任务划分,
// 同步任务:new Promise()、console.log('4');
// 宏任务: setTimeout();
// 微任务:Promise().then();
// Event Loop依次将同步任务推入执行栈并执行,当遇到宏任务或微任务时,推到宏任务或微任务队列中,同步队列执行完毕,会去微队列取任务,直到微队列清空,再去宏队列取任务执行。故此段程序执行顺序为:new Promise()、console.log('4')、Promise().then()、setTimeout()。JS 事件机制 (原生事件绑定、事件冒泡、事件委托、事件监听、阻止默认事件触发) - 见《JS 高级程序设计》第13章
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 深拷贝
这个网上太多了,大伙自己去看。
7、ES6 新特性
箭头函数:箭头函数与普通函数在原理与使用上有哪些区别呢?
Promise相关
Promise的实现原理以及代码。用 Promise 函数实现 sleep 函数是滴滴二面代码题之一
let/const/var
async/await
前端模块化
ES6 与 ES5 对比性学习:如何用ES5来实现ES6中的Class功能?
CSS基础篇
这一部分的知识点大都偏记忆型,较为简单。虽不需要特地花时间去背,但需注重积累,建议在实战开发过程中,养成随时理解、随手记录的习惯。
- HTML 各类标签(块级、行内元素的定义以及二者相互转换几乎是每场技术一面必考问题)
- HTML5中新增的语义化标签、客户端存储方案、websocket等
- CSS各类常用的属性是必要的
- 浮动、清除浮动以及定位更是必考点。
- CSS盒模型(盒模型的类型、切换模式、计算不同盒模型下盒子宽高)
- CSS各类选择器(各个选择器优先级顺序、多个选择器组合时优先级比重的计算)
- CSS中的伪类与伪元素在实际开发中使用频率很高(比如鼠标在标签上的四种状态,利用伪元素在元素前后添加一些不在DOM tree的元素等)
- CSS3 的新特性
- 常见布局(盒子页面居中、两栏、三栏自适应布局、BFC布局、Flex布局、table布局、grid布局、移动端布局(rem、流式、自适应、响应式)。这些布局实现方法有很多种,比如三栏布局可用圣杯布局、双飞翼布局、Flex布局、table布局等多种方法实现,故学习时要掌握多种实现方法,同时要加以自己的理解灵活变通。BFC布局可用来清除浮动、解决margin坍塌重叠等问题,几乎是第一轮技术面必考问题。Flex布局原理与应用也是技术面中的高频考点,可以直接看阮一峰老师的Flex布局教程。)
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需要合成事件
“兼容性的考虑把,可以抹平不同浏览器事件对象差异,还有个就是避免了垃圾回收。”
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做转换最后生成。”
系统
可视化技术/图形学
设计模式与工程化
Webpack 原理,常见 loader
MVC,MVVM
计算机网络
OSI七层模型、各层中的传输协议、TCP/UDP区别、TCP三次握手四次挥手、HTTP/HTTPS区别、HTTP各版本、HTTP报文结构等等。
浏览器的网络攻防问题千万不可忽视,常见的攻击如CSRF、XSS、SQL注入的攻击原理与途径,应对的防御措施都需要熟悉与理解,多看一些常见攻击案例,如经典的CSRF银行案例,不仅有助于理解,在面试时也能通过举例阐述得更加清楚。
数据结构与算法
- 数组、链表、队列、栈、Set、Map、哈希表
- JS代码实现数据结构
- 排序算法与一些其他算法题。快速排序、归并排序、堆排序、冒泡排序、插入排序、选择排序、希尔排序、桶排序、基数排序、Timsort这十种,
前端必撕代码
深拷贝、防抖节流、手写Promise、Promise实现Sleep函数、原型链、CSS画三角形、自适应布局、JS继承、数组去重、Ajax请求过程等。
1 | #纯CSS画三角形 |
常考智力题
25匹马赛跑、烧绳子、药丸质量检测、3L和5L杯子倒出4L的水等等