春招博客笔记
以下是春招时候准备时候看的一些技术博客,受到这两个项目的启发:
决定自己也写一个类似的,之前看过的没有记录,之后看到的好的技术博客打算随缘以这种方式做笔记。
链接就是对应的博客,底下的文字部分是我看完之后做出的注解。
目录
CSS
BFC
一个背诵题,文章没有写太多门道。
主要就五种常见的 BFC 情景和三种主要的 BFC 的作用。
flex 布局和基本概念
Mastering Wrapping of Flex Items
主要介绍了 flex 布局的相关内容,MDN 的文档质量真的高,无论是中文的还是英文的。
flex 布局有几个关键点,首先是通过 flex-direction 来设置布局的方向,flex 设计的初衷是将所有的元素放在一行或者一列上,但是 flex-wrap 这个属性就对 flex 布局进行了拓展,它允许在原来模式下将要溢出的内容另起一行或者一列进行展示。
第二篇文章着重讲解了 flex 布局和 grid 布局的差异。flex 只能进行一维布局上的安排,虽然可以通过禁止伸缩的方式达到一些特殊的目的,但是设计初衷就是在一行或者一列上考虑。如果需要二维设计最好采用 grid 优雅的实现。
JavaScript
闭包
这个文章写的相当好,这个作者的这个系列非常厉害,将这个问题难得地讲的很清楚。
这个中间涉及的东西有点多,名词也比较多,我稍微凭着记忆梳理一下。
首先,JS 是一门静态作用域的语言,变量的作用域在函数定义的时候就已经决定了,而不是在函数执行的过程中。
具体到嵌套的函数,函数会维护一个“作用域链”,函数首先在自己的变量集合中找变量,找不到会沿着作用域链逐层向上,直到最后一个节点(也就是全局),这个过程解释了为什么“靠里面”的变量会屏蔽靠外的。文章中有一点没有明说但是很重要, 就是当函数的某个变量有一个外部引用时,整个作用域链都不会销毁。 这也就是闭包的原理。
扩展一点,具体到一个函数的执行过程,其中只有传入的参数在一开始是有预设值的,其他的变量都必须先赋值再使用,包括函数的声明, 函数内的函数声明没有一个全局中的类似提升的过程 。同时当这个过程完成的时候,如果存在嵌套的函数,这些变量都将保存下来待查。
前端模块化
这个看的有点一头雾水,没有完全的看明白之间的区别。
首先从思想上,模块化经历了多个 function 函数->写在一个对象里->函数自调用的闭包三个阶段,第一个的问题是散乱容易污染全局变量,第二个的问题是暴露了内部的变量,没有体现封装。
然后在工程实践上面,分别是经历了 CommonJS -> AMD -> CMD -> ES6 的过程。这个过程没有理解的很透彻,目前只是对形式有一个机械的记忆,就先不多写了。
事件循环
Promise 使用
async 和 await
异步函数的相关东西,解释 JS 这样的单线程语言怎么处理并行的情况。
总的来说,就是维护了消息队列这样一个东西,在 Promise 出来之后又将宏任务和微任务做了区别,JS 执行引擎先执行一段代码,然后别的线程就完成之后的工作,等结束之后将预先设定的回调函数加入消息队列,JS 执行引擎在执行栈空了之后就去挨个执行微任务队列里面的回调函数,再从宏任务消息队列里面取一个回调函数执行,等这个执行完了再去扫描微任务消息队列,如此往复…
内存泄漏
文章通俗易懂,之前写代码的时候没有这个概念,面试的时候面试官问了一个“ Vue 销毁前的钩子函数可以做些什么”,完全不知道是在问这个东西。
首先要防止内存泄漏,就要知道 JS 的垃圾回收机制,很巧妙的,JS 的垃圾回收和 Java 几乎一毛一样。对于新生代的对象,采用“复制转移”的办法,对于旧的对象,从根节点维护一棵引用的树,对于不可到达的对象进行清理。
知道了这个,接下来就容易理解了:
- 全局变量一定要谨慎,如果在全局定义了很多“一次性”的大对象,那么它们永远不会被清理。
- 然后是 setInterval,必须手动的销毁定时器。
- 还有就是事件的监听器,之前以为组件销毁之后这些不用手动处理,看了文章才知道 Vue 中最好在 beforeDestory 阶段移除掉。
- 还有事件发布的相关东西,emit 的基本没做什么处理,难受。
- 还有 Map 和 Set 的引用,但是这个不一定,不用外部引用也可以循环找到,但有些特殊场合可以用 WeakMap 和 WeakSet。
- document 提供各种方法 get 到的 dom,也必须手动把引用移除了。
- 闭包,如果不移除的话作用域链一直维护着,JS 引擎表示心累。
最后还介绍了一下内存泄漏的检测方法,很实用,感觉这个玩意可以在毕业设计论文优化里面写。
浏览器
白屏优化
这个博客写的相当简略。
首先,根据文中的定义,实际上这个问题就是“打开 URL 之后发生了什么”这个经典问题的一个变种,那么思路就是在这个过程的各个阶段进行优化。
这个过程主要是以下几个过程:DNS 连接-> HTTP / HTTPS -> 计算机网络那几层传输 -> 服务器响应 -> 浏览器构建网页。
从这个角度来回答问题,DNS 主要考虑多级缓存加上 CDN;HTTP 可以回答持久连接、缓存机制、流水线传输、服务器推送、部分请求响应等等;网络层可以按照各个层针对的想办法,什么减少拥堵、铜线改光纤啊等等;服务器响应后端搞得比较多,主要是分布式、数据库优化等等;浏览器构建可以详细的说说。
浏览器构建主要有以下几个大的步骤:DOM 树/ CSSOM 树的构建-> render 树 -> 布局 -> 渲染。
针对前两步,主要防止 JS 对过程的阻塞,因此一般将 JS 脚本放在 HTML 文件的最后,针对后两步,在这个问题没有什么太多的内容,主要是减少重排/重绘可以做些安排。
浏览器缓存
看着有点乱,稍微总结一下,浏览器缓存分为强制缓存和协商缓存两个过程,强制缓存可以看作浏览器和浏览器缓存的交互过程,对应字段是 expires/cache-control。
当缓存过期后,浏览器向服务端发送缓存的识别码,对应字段是 if-motified-since 和 if-none-match ,服务端通过这两个字段判断是哪个“版本”的缓存。这就是协商缓存。
最后就是浏览器加载完成后,CSS 文件保存在硬盘缓存中,而图片和 JS 内容则在内存缓存中。协议缓存时候使用浏览器自己的缓存状态码 304,更新内容的话则是 200。
算法
二分查找
注意边界的记忆,没有什么难度,就是记住就好了。
采用闭区间的方法比较好记,首先把左右节点放在两边能取到的节点上,然后循环条件因为能取到带等号。寻找左侧边界动右侧验左侧,反过来就是验左侧,动右侧。