HTML浏览器缓存问题(涉及到:http强缓存与协商缓存)
5.缓存问题(涉及到:http强缓存与协商缓存,缓存头,etag,expired,cache-control等)
6.浏览器接受到http数据包后的解析流程(涉及到html词法分析,解析成DOM树,解析CSS生成CSSOM树,合并生成render渲染树。然后layout布局,painting渲染,复合图层合成,GPU绘制,外链处理等)
7.css可视化模型(涉及到:元素渲染规则,如:包含块,控制框,BFC,IFC等)
8.JS引擎解析过程(涉及到:JS解析阶段,预处理阶段,执行阶段生成执行上下文,VO(全局对象),作用域链,回收机制等)
你会发现一个简单的输入URL到页面呈现,之间会发生这么多过程,是不是瞬间觉得崩溃了?(别急,这一章我们不讲这么深,先教你如何回答这个问题,后面这一节单独出文章讲)
4.浏览器是如何解析代码的?解析HTML
HTML是逐行解析的,浏览器的渲染引擎会将HTML文档解析并转换成DOM节点。
解析CSS
浏览器会从右往左解析CSS选择器
我们知道DOM树与CSSOM树合并成render树,实际上是将CSSOM附着到DOM树上,因此需要根据选择器提供的信息对DOM树进行遍历。
我们看一个例子?:
.nav .title span {color:blue}
南玖
前端
从右至左的匹配:
先找到所有的最右节点 span,对于每一个 span,向上寻找节点 div.title由 h3再向上寻找 div.nav 的节点最后找到根元素 html 则结束这个分支的遍历。解析JS
在浏览器中有一个js解析器的工具,专门用来解析我们的js代码。
当浏览器遇到js代码时,立马召唤“js解析器”出来工作。
解析器会找到js当中的所有变量、函数、参数等等,并且把变量赋值为未定义(undefined)。
把函数取出来成为一个函数块,然后存放到仓库当中。这件事情做完了之后才开始逐行解析代码(由上向下,由左向右),然后再去和仓库进行匹配。
5.DOMContentLoaded与load的区别?6.浏览器重绘域重排的区别?
重绘不一定导致重排,但重排一定绘导致重绘
如何触发重绘和重排?
任何改变用来构建渲染树的信息都会导致一次重排或重绘:
如何避免重绘或重排?
提升合成层的最好方式是使用 CSS 的 will-change 属性:
#target {
will-change: transform;
}
7.为什么JS是单线程的?
这主要与JS的用途有关,JS作为浏览器的脚本语言,最初主要是实现用户与浏览器的交互,以及操作DOM。这就决定了它只能是单线程,否则会带来许多复杂的同步问题。
举个例子?: 如果JS是多线程的,其中一个线程要修改一个DOM元素,另外一个线程想要删除这个DOM元素,这时候浏览器就不知道该听谁的。所以为了避免复杂性js单线程 ui渲染,从一诞生,JavaScript就被设计成单线程。
为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质
8.CSS加载会阻塞DOM吗?先上结论CSSOM的作用
由之前讲到的浏览器渲染流程我们可以看出:
JS需要等待CSS的下载,这是为什么呢?(CSS阻塞DOM执行)
如果JS脚本的内容是获取元素的样式,那它就必然依赖CSS。因为浏览器无法感知JS内部到底想干什么,为避免样式获取,就只好等前面所有的样式下载完毕再执行JS。但JS文件与CSS文件下载是并行的,CSS文件会在后面的JS文件执行前先加载执行完毕,所以CSS会阻塞后面JS的执行
避免白屏,提高CSS的加载速度9.JS会阻塞页面吗?先上结论
JS会阻塞DOM的解析,因此也就会阻塞页面的加载
这也是为什么我们常说要把JS文件放在最下面的原因
由于 JavaScript 是可操纵 DOM 的,如果在修改这些元素属性同时渲染界面(即 JavaScript 线程和 UI 线程同时运行),那么渲染线程前后获得的元素数据就可能不一致了。
因此为了防止渲染出现不可预期的结果,浏览器设置 「GUI 渲染线程与 JavaScript 引擎为互斥」的关系。
当 JavaScript 引擎执行时 GUI 线程会被挂起,GUI 更新会被保存在一个队列中等到引擎线程空闲时立即被执行。
当浏览器在执行 JavaScript 程序的时候,GUI 渲染线程会被保存在一个队列中,直到 JS 程序执行完成,才会接着执行。
因此如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
10.defer和async的区别?11.浏览器的垃圾回收机制
垃圾回收是一种自动的内存管理机制。当计算机上的动态内存不再需要时,就应该予以释放。
需要注意的是,自动的意思是浏览器可以自动帮助我们回收内存垃圾,但并不代表我们不用关心内存管理,如果操作不当,JavaScript中仍然会出现内存溢出的情况,造成系统崩溃。
由于字符串,数组,对象等都没有固定大小,因此需要当它们大小已知时,才能对他们进行动态的存储分配。JavaScript程序每次创建字符串,数组或对象时,解释器都必须分配内存来存储那个实体。
JavaScript解释器可以检测到何时程序不在使用一个对象了,当它确定这个对象是无用的时候,他就知道不再需要这个对象了,就可以把它占用的内存释放掉了。
浏览器通常采用的垃圾回收有两种方法:标记清除,引用计数。
标记清除
这是JavaScript中最常用的垃圾回收方式
从2012年起,所有现代浏览器都使用了标记清除的垃圾回收方法,除了低版本IE还是采用的引用计数法。
那么什么叫标记清除呢?
JavaScript中有一个全局对象,定期的,垃圾回收器将从这个全局对象开始,找出所有从这个全局对象开始引用的对象,再找这些对象引用的对象...对这些活跃的对象标记,这是标记阶段。清楚阶段就是清楚那些没有被标记的对象。
标记清除有一个问题,就是在清除之后,内存空间是不连续的,即出现了内存碎片。如果后面需要一个比较大的连续的内存空间,那将不能满足要求。而标记整理 方法可以有效德地解决这个问题。
在标记的过程中,引入了概念:三色标记法,三色为:
标记整理:
标记阶段与标记清除法没什么区别,只是标记结束后,标记整理法会将存活的对象向内存的一边移动,最后清理掉边界内存。
引用计数
引用计数的含义是跟踪记录每个值被引用的次数。当一个变量A被赋值时,这个值的引用次数就是1,当变量A重新赋值后,则之前那个值的引用次数就减1。当引用次数变成0时,则说明没有办法再访问这个值了,所以就可以清除这个值占用的内存了。
大多数浏览器已经放弃了这种回收方式
内存泄漏
为避免内存泄漏,一旦数据不再使用,最好通过将其值设为null来释放其引用,这个方法叫做接触引用
哪些情况会造成内存泄漏?如何避免?
以 Vue 为例,通常有这些情况:
解决办法:beforeDestroy 中及时销毁
浏览器中不同类型变量的内存都是何时释放的?基本类型12.说一说浏览器的缓存机制?认识浏览器缓存
当浏览器请求一个网站时,会加载各种资源,对于一些不经常变动的资源,浏览器会将他们保存在本地内存中,下次访问时直接加载这些资源,提高访问速度。
如何知道资源是请求的服务器还是读取的缓存呢?
看上面这张图,有些资源的size值是大小,有些是from disk cache,有些是from memory cache,显示大小的是请求的服务器资源,而显示后面两种的则是读取的缓存。
-memory cachedisk cache
相同点
只能存储一些派生类资源文件
只能存储一些派生类资源文件
不同点
退出进程时数据会被清除
退出进程时数据不会被清除
存储资源
一般脚本、字体、图片会存在内存当中
一般非脚本会存在内存当中,如css等
浏览器缓存分类
浏览器在向服务器请求资源时,首先判断是否命中强缓存,没命中再判断是否命中协商缓存
强缓存
浏览器在加载资源时js单线程 ui渲染,会先根据本地缓存资源的header中判断是否命中强缓存,如果命中则直接使用缓存中的资源,不会再向服务器发送请求。(这里的header中的信息指的是 expires 和 cache-control)
Expires
该字段是 http1.0 时的规范,它的值为一个绝对时间的 GMT 格式的时间字符串,比如 Expires:Mon,18 Oct 2066 23:59:59 GMT。这个时间代表着这个资源的失效时间,在此时间之前,即命中缓存。这种方式有一个明显的缺点,由于失效时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱。所以这种方式很快在后来的HTTP1.1版本中被抛弃了。
Cache-Control
Cache-Control 是 http1.1 时出现的 header 信息,主要是利用该字段的 max-age 值来进行判断,它是一个相对时间,例如 Cache-Control:max-age=3600,代表着资源的有效期是 3600 秒。cache-control 除了该字段外,还有下面几个比较常用的设置值:
no-cache:需要进行协商缓存,发送请求到服务器确认是否使用缓存。
no-store:禁止使用缓存,每一次都要重新请求数据。
public:可以被所有的用户缓存,包括终端用户和 CDN 等中间代理服务器。
private:只能被终端用户的浏览器缓存,不允许 CDN 等中继缓存服务器对其缓存。
Cache-Control 与 Expires 可以在服务端配置同时启用,同时启用的时候 Cache-Control 优先级高。
协商缓存
当强缓存没命中时,浏览器会发送一个请求到服务器,服务器根据 header 中的信息来判断是否命中协商缓存。如果命中,则返回304 ,告诉浏览器资源未更新,可以使用本地缓存。(这里的header信息指的是Last-Modify/If-Modify-Since 和 ETag/If-None-Match)
Last-Modify/If-Modify-Since
浏览器第一次请求一个资源的时候,服务器返回的 header 中会加上 Last-Modify,Last-modify 是一个时间标识该资源的最后修改时间。
当浏览器再次请求该资源时,request 的请求头中会包含 If-Modify-Since,该值为缓存之前返回的 Last-Modify。服务器收到 If-Modify-Since 后,根据资源的最后修改时间判断是否命中缓存。
如果命中缓存,则返回 304,并且不会返回资源内容,并且不会返回 Last-Modify。
缺点:
短时间内资源发生了改变,Last-Modified 并不会发生变化。
周期性变化。如果这个资源在一个周期内修改回原来的样子了,我们认为是可以使用缓存的,但是 Last-Modified 可不这样认为,因此便有了 ETag。
ETag/If-None-Match
与 Last-Modify/If-Modify-Since 不同的是,Etag/If-None-Match 返回的是一个校验码。ETag 可以保证每一个资源是唯一的,资源变化都会导致 ETag 变化。服务器根据浏览器上送的 If-None-Match 值来判断是否命中缓存。
与 Last-Modified 不一样的是,当服务器返回 304 Not Modified 的响应时,由于 ETag 重新生成过,response header 中还会把这个 ETag 返回,即使这个 ETag 跟之前的没有变化。
Last-Modified 与 ETag 是可以一起使用的,服务器会优先验证 ETag,一致的情况下,才会继续比对 Last-Modified,最后才决定是否返回 304。
总结
当浏览器访问一个已经访问过的资源是,它的步骤是:
1.先看是否命中强缓存,命中?的话直接使用缓存
2.没命中强缓存,则会发送请求到服务器看是否命中?协商缓存
3.如果命中了协商缓存,服务器会返回304告诉浏览器可以使用本地缓存
4.没命中协商缓存,则服务器会返回新的资源给浏览器
13.什么是浏览器的同源策略,以及跨域?同源策略
同源策略是浏览器的一种自我保护行为。所谓的同源指的是:协议,域名,端口均要相同
浏览器中大部分内容都是受同源策略限制的,但是以下三个标签不受限制:
跨域
跨域指的是浏览器不能执行其它域名下的脚本。它是由浏览器的同源策略限制的。
你可能会想跨域请求到底有没有发送到服务器?
事实上,跨域请求时能够发送到服务器的,并且服务器也能过接受的请求并正常返回结果,只是结果被浏览器拦截了。
跨域解决方案(列出几个常用的)JSONP
它主要是利用script标签不受浏览器同源策略的限制,可以拿到从其他源传输过来的数据,需要服务端支持。
优缺点:
兼容性比较好,可用于解决主流浏览器的跨域数据访问的问题。缺点就是仅支持get请求,具有局限性,不安全,可能会受到XSS攻击。
思路:
发表评论
热门文章
Spimes主题专为博客、自媒体、资讯类的网站设计....
一款个人简历主题,可以简单搭建一下,具体也比较简单....
仿制主题,Typecho博客主题,昼夜双版设计,可....
用于作品展示、资源下载,行业垂直性网站、个人博客,....
尘集杂货铺和官网1t5-cn
11月11日
[已回复]
希望主题和播放器能支持SQLite数据库,AI能多个讯飞星火