常见的浏览器内核有哪些?
Trident内核:IE,MaxThon,TT,The World,360,搜狗浏览器等。[又称MSHTML]
Gecko内核:Netscape6及以上版本,FF,MozillaSuite/SeaMonkey等
Presto内核:Opera7及以上。 [Opera内核原为:Presto,现为:Blink;]
Webkit内核:Safari,Chrome等。 [ Chrome的:Blink(WebKit的分支)]
CSS解析规则
浏览器会从右往左(从下向上-树形)解析CSS选择器
<style>
.header .title span { color: red; }
</style>
浏览器匹配规则如下
- 先找到所有的最右节点
span
,对于每一个span
节点,向上寻找节点.title
- 继续找
.header
的节点 - 最后找到根元素 html 则结束这个分支的遍历
CSS加载会阻塞DOM吗
- CSS不会阻塞DOM的解析,但会阻塞DOM的渲染
- CSS会阻塞JS执行,但不会阻塞JS文件的下载
针对第一点,阐明原因
- DOM和CSSOM通常是并行构建的,所以CSS加载不会阻塞DOM的解析
- render树是依赖DOM树和CSSOM树的,所以它必须等到两者都加载完毕才能开始构建渲染,所以CSS加载会阻塞DOM的渲染
针对第二点,阐明原因
如果JS脚本的内容是获取元素的样式,那它就必然依赖CSS。因为浏览器无法感知JS内部到底想干什么,为避免样式获取,就只好等前面所有的样式下载完毕再执行JS。但JS文件与CSS文件下载是并行的,CSS文件会在后面的JS文件执行前先加载执行完毕,所以CSS会阻塞后面JS的执行
JS会阻塞页面渲染吗?
- JS会阻塞DOM的解析,因此也就会阻塞页面的加载
原因:GUI 渲染线程与 JavaScript 引擎为互斥
DOMContentLoaded与load的区别
DOMContentLoaded
:仅当DOM解析完成后触发,不包括样式表,图片等资源
load
:当页面上所有的DOM,样式表,脚本,图片等资源加载完毕事触发。
defer和async的区别?
- 两者都是异步去加载外部JS文件,不会阻塞DOM解析
async
是在外部JS加载完成后,浏览器空闲时,load
事件触发前执行,标记为async
的脚本并不保证按照指定他们的先后顺序执行,该属性对于内联脚本无作用- defer是在JS加载完成后,整个文档解析完成后,触发
DOMContentLoaded
事件前执行,如果缺少src
属性(即内嵌脚本),该属性无法起作用
什么是浏览器的同源策略
同源策略是浏览器的一种自我保护行为。所谓的同源指的是:协议,域名,端口均要相同
但是标签不受限制,所有可能会有安全问题
<img src="..." />
<link href="..." />
<script src="..."></script>
如何解决跨域问题?
jsonp
它主要是利用script标签不受浏览器同源策略的限制,可以拿到从其他源传输过来的数据,需要服务端支持。
缺点:就是仅支持get请求,具有局限性,不安全,可能会受到XSS攻击。
跨域资源共享(CORS)
nginx反向代理
通过nginx或者服务器配置 Access-Control-Allow-Origin
响应头
浏览器的缓存机制
浏览器缓存分类
分为两种:强缓存,协商缓存
浏览器在向服务器请求资源时,首先判断是否命中强缓存,没命中再判断是否命中协商缓存
强缓存:浏览器在加载资源时,会先根据本地缓存资源的 expires 或者 cache-control 判断是否命中强缓存,如果命中则直接使用缓存中的资源,不会再向服务器发送请求
协商缓存:协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程
强缓存
Expires: 需和Last-Modified结合使用,用于控制请求文件的有效时间。缺点:Expires 是 HTTP/1 的产物,受限于本地时间,如果修改了本地时间,可能会造成缓存失效
Cache-Control:主要是利用该字段的 max-age 值来进行判断,它是一个相对时间,例如 Cache-Control: max-age=3600,代表着资源的有效期是 3600 秒
Cache-Control 与 Expires 一起使用时,Cache-Control优先级高
Cache-Control可配置值
字段 | 说明 |
---|---|
no-cache | 需要进行协商缓存,发送请求到服务器确认是否使用缓存。 |
no-store | 禁止使用缓存,每一次都要重新请求数据。 |
public | 可以被所有的用户缓存,包括终端用户和 CDN 等中间代理服务器。 |
private | 只能被终端用户的浏览器缓存,不允许 CDN 等中继缓存服务器对其缓存。 |
协商缓存
Last-Modify/If-Modify-Since:根据文件的修改时间来判断是否缓存,缺点是文件无改动,但是文件修改时间改动,会导致缓存失效
ETag/If-None-Match:根据文件的内容hash值来判断是否缓存
Last-Modify 与 ETag 一起使用时,ETag优先级高
事件循环
JS引擎常驻于内存中,等待宿主将JS代码或函数传递给它。
也就是等待宿主环境分配宏观任务,反复等待 - 执行即为事件循环。
<img src="/static/imgs/event-loop.webp" />
Event Loop中,每一次循环称为tick,每一次tick的任务如下:
- 执行栈选择最先进入队列的宏任务(一般都是script),执行其同步代码直至结束;
- 检查是否存在微任务,有则会执行至微任务队列为空;
- 如果宿主为浏览器,可能会渲染页面;
- 开始下一轮tick,执行宏任务中的异步代码(setTimeout等回调)。
<div className="google-adsense" data-slot="5116803225" />
微任务和宏任务
ES6 规范中,microtask 称为 jobs,macrotask 称为 task
宏任务是由宿主发起的,而微任务由JavaScript自身发起。
宏任务
(macro)task,可以理解是每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)。
浏览器为了能够使得JS内部(macro)task与DOM任务能够有序的执行,会在一个(macro)task执行结束后,在下一个(macro)task 执行开始前,对页面进行重新渲染,流程如下:
(macro)task->渲染->(macro)task->...
宏任务包含:
script(整体代码)
setTimeout
setInterval
I/O
UI交互事件
postMessage
MessageChannel
setImmediate(Node.js 环境)
微任务
(micro)task,可以理解是在当前 task 执行结束后立即执行的任务。也就是说,在当前task任务后,下一个task之前,在渲染之前。
所以它的响应速度相比setTimeout(setTimeout是task)会更快,因为无需等渲染。也就是说,在某一个macrotask执行完后,就会将在它执行期间产生的所有microtask都执行完毕(在渲染前)。
微任务包含:
Promise.then
Object.observe
MutationObserver
process.nextTick(Node.js 环境)
从输入URL到页面加载发生了什么?
- URL解析,判断是URL还是搜索关键字,如果是URL就开始进行DNS解析,关键字就进行搜索
- DNS解析到具体的IP地址
- 浏览器三次握手建立TCP连接,向服务端请求页面
- 服务端响应浏览器请求,返回HTML代码等资源
- TCP4次挥手断开连接
- 浏览器解析HTML文件,生成DOM和CSSOM,构建render树,渲染到页面
无论你是前端初学者还是有两三年的前端开发,这个网址整理了最新最全的面试题,永久免费,欢迎收藏转发!
永久免费,专门针对前端人的学习
整理好的文章和资料也不容易,如果觉得好用也可以转发给你身边的小伙伴们
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。