跳到主内容

浏览器基础面试题(一)

常见的浏览器内核有哪些?

Trident内核:IE,360,搜狗等浏览器

Gecko内核:Netscape6及以上版本,Firefox

Blink内核:Opera7及以上

Webkit内核:Safari,Chrome

CSS解析规则

浏览器会从右往左(从下向上-树形)解析CSS选择器,减少遍历失败回溯的次数

<style>
.header .title span { color: red; }
</style>

浏览器匹配规则如下

先匹配 span 元素,然后向上寻找 .title .header 的节点,直到根元素 html 结束

CSS加载会阻塞DOM吗

CSS会阻塞JS执行,但不会阻塞JS文件的下载

  • 浏览器在渲染页面的时候,如果JS在此期间同步操作样式或者获取样式,会导致页面渲染混乱,所以需要等待CSS执行完才能执行JS

  • JS文件与CSS文件下载是并行的,CSS文件会在后面的JS文件执行前先加载执行完毕,所以CSS会阻塞后面JS的执行

CSS不会阻塞DOM的解析,但会阻塞DOM的渲染

  • 浏览器在生成DOM树和CSSOM树通常是并行构建的,所以CSS不会阻塞DOM的解析
  • 浏览器在渲染等待DOM树和CSSOM树构建完成生成render树才开始渲染,所以CSS加载会阻塞DOM的渲染

JS会阻塞页面渲染吗?

JS引擎和渲染引擎是互斥的,因此JS执行的时候渲染引擎就会挂起,所以会阻塞页面的渲染

根本原因:GUI 渲染线程与 Javascript 引擎为互斥

DOMContentLoaded与load的区别

DOMContentLoaded:当DOM解析完成后触发,不包括JS,CSS,图片等静态资源

load:当HTML,CSS,JS,图片等所有资源加载完成后触发

由此可见,DOMContentLoaded 事件提前于 load 事件触发

defer和async的区别?

  • 都是异步去加载JS文件,不会阻塞DOM树解析

  • async 是在JS加载完成后,load 事件触发前立刻执行,标记为 async 的脚本并不保证执行的顺序,该属性对于内联脚本无作用

  • defer 是在JS加载完成后,文档解析完成后,触发 DOMContentLoaded 事件前执行

什么是浏览器的同源策略

同源策略是一个重要的安全策略,它用于限制一个【源】如何能与【另一个源】的资源进行交互。主要是浏览器对资源的安全控制,防止跨域访问。

如何判断是否同源

很简单,只要协议相同域名相同端口号相同,就属于同源

下表给出了与 URL http://www.1024nav.com/dir/page.html 的源进行对比的示例:

URL结果原因
http://www.1024nav.com/front-junior/browser/basic同源只有路径不同
http://www.1024nav.com/front-senior/browser/basic同源只有路径不同
https://www.1024nav.com/front-junior/browser/basic失败协议不同
http://www.1024nav.com:8080/front-junior/browser/basic失败端口不同
http://interview.1024nav.com/front-junior/browser/basic失败域名不同

注意:标签不受同源策略的限制,所有可能会有安全问题

<img src="..." />
<link href="..." />
<script src="..."></script>

如何解决跨域问题?

更详细的跨域实现,可以参阅 前端跨域的具体实现

浏览器的缓存机制

浏览器缓存分类

浏览器缓存分为两种:强缓存协商缓存

强缓存:浏览器在请求静态资源的时候,会根据静态资源的 Cache-ControlExpires 判断是否超期,如果未超期则无需向服务器发起请求,直接使用缓存的文件

协商缓存:强缓存失效后,浏览器向服务端发起请求静态资源,服务端根据请求头的 ETagLast-Modify 判断资源是否失效,如果失效返回新的资源,未失效则告诉浏览器使用磁盘的缓存

如何控制强缓存

强缓存的控制请求头和响应头分别有

  • Expires 和 Last-Modified
  • Cache-Control

两者都存在的情况下,Cache-Control的优先级更高

如何控制协商缓存

协商缓存的控制请求头和响应头分别有

  • Last-Modify 和 If-Modify-Since
  • Etag 和 If-None-Match

两者都存在的情况下,ETag的优先级更高

事件循环

由于JS是单线程的,浏览器为了能处理一些数据请求,定时器等异步任务,引入了事件循环机制。

在一个事件循环中,浏览器执行的流程如下

  • 执行宏任务代码(SCRIPT代码),中途遇到微任务的回调,入微任务队列,一直到执行完毕
  • 检测微任务队列是否为空,不为空弹出执行一直到执行完毕,中途有新的任务进来继续执行直到队列清空
  • 执行宏任务达到条件的回调直至清空

微任务和宏任务

宏任务

宏任务一般是由浏览器发起的,比如SCRIPT代码,异步请求(ajax请求),事件回调,定时器等。

宏任务包含

script(整体代码)
setTimeout
setInterval
I/O
UI交互事件
postMessage
MessageChannel
setImmediate(Node.js 环境)

微任务

微任务一般是由JS自身创建,比如 PromiseMutationObserverObject.observe ·,process.nextTick

从输入URL到页面加载发生了什么?

  1. 进行DNS解析,得到具体的服务器IP地址
  2. 客户端三次握手建立TCP连接后,向服务器发送请求HTML
  3. 服务器响应HTML文件给浏览器,浏览器开始解析,请求CSS资源和JS资源,生成DOM树和CSSOM树,构建render树,最终渲染到页面

如果想深入了解,可以到这篇文章