我将围绕浏览器常见面试题及答案,从浏览器组成、内核、渲染机制、缓存等方面展开阐述,并结合实际应用场景,帮助你更好地理解和掌握相关知识。
浏览器常见面试题及答案
在前端开发领域,对浏览器相关知识的理解和掌握是至关重要的。无论是基础的浏览器组成、内核类型,还是复杂的渲染机制、缓存策略,都是面试中常见的考察点。本文将详细梳理一些浏览器常见面试题及其答案,助力大家在面试中脱颖而出,同时也为日常开发提供知识储备。
一、浏览器的主要组成部分
- 用户界面:这是用户与浏览器交互的直接部分,包括地址栏、前进/后退按钮、书签菜单、刷新按钮、停止按钮等。它负责接收用户的输入和操作指令,并向用户展示网页的加载状态、页面标题等信息。例如,用户在地址栏输入网址,点击前进或后退按钮切换浏览历史等操作,都是通过用户界面完成的。
- 浏览器引擎:作为用户界面和呈现引擎之间的桥梁,浏览器引擎负责传送指令。它接收用户界面传来的操作指令,如加载网页、切换页面等,然后将这些指令传达给呈现引擎进行处理。同时,它也会将呈现引擎的处理结果反馈给用户界面,以便用户界面做出相应的显示更新。
- 呈现引擎:呈现引擎是浏览器的核心组件之一,其主要职责是显示请求的内容。当请求的内容是HTML页面时,它会解析HTML和CSS内容,并将解析后的结果以可视化的形式显示在屏幕上。不同的浏览器使用不同的呈现引擎,例如Chrome浏览器使用的Blink引擎,Safari浏览器使用的WebKit引擎等。呈现引擎在解析HTML时,会构建DOM树(文档对象模型树),同时解析CSS构建CSSOM树(层叠样式表对象模型树),最后将两者合并成渲染树,根据渲染树来绘制页面。
- 网络模块:用于处理网络调用,如发起HTTP请求、HTTPS请求等。在加载网页时,网络模块负责与服务器建立连接,发送请求并接收服务器返回的响应数据。它还会处理请求过程中的各种情况,如请求超时、网络错误等。例如,当浏览器请求一个图片资源时,网络模块会根据图片的URL发起HTTP请求,从服务器获取图片数据,并将其传递给呈现引擎进行显示。
- 用户界面后端:主要用于绘制基本的窗口小部件,如组合框、按钮、滚动条等。它提供了一些基础的图形绘制功能,使得用户界面能够以直观、友好的方式呈现给用户。这些窗口小部件的绘制风格和样式通常由操作系统或浏览器的主题设置决定。
- JavaScript解释器:负责解析和执行JavaScript代码。在网页中,JavaScript常用于实现各种交互功能,如表单验证、动态内容更新、页面特效等。JavaScript解释器会逐行解析JavaScript代码,并将其转换为机器能够理解的指令来执行。不同的浏览器有不同的JavaScript解释器,例如Chrome浏览器的V8引擎,它以高性能和快速的JavaScript执行速度而闻名。
- 数据存储:浏览器需要在硬盘上保存各种数据,这就是数据存储模块的作用。常见的数据存储方式包括Cookie、Web Storage(包括localStorage和sessionStorage)、IndexDB等。Cookie常用于存储用户的登录状态、偏好设置等信息,它会在每次HTTP请求时被发送到服务器。Web Storage则主要用于在客户端本地存储数据,其中localStorage的数据会一直保存在本地,除非手动删除;sessionStorage的数据只在当前会话期间有效,关闭浏览器窗口或标签页后数据会被清除。IndexDB是一种更强大的客户端数据库,适用于存储大量结构化数据。
二、常见的浏览器内核有哪些
| 浏览器/RunTime | 内核(渲染引擎) | JavaScript引擎 |
|---|---|---|
| Chrome | webkit->blink | V8 |
| FireFox | Gecko | SpiderMonkey |
| Safari | Webkit | JavaScriptCore |
| Edge | EdgeHTML | Chakra(for JavaScript) |
| IE | Trident | JScript(IE3.0 - IE8.0) |
| Opera | Presto->blink | Linear A(4.0 - 6.1)/ Linear B(7.0 - 9.2)/ Futhark(9.5 - 10.2)/ Carakan(10.5 - ) |
| Node.js | - | V8 |
- Chrome:早期使用WebKit内核,后来为了更好地满足自身的发展需求,从WebKit分支出来开发了Blink内核。Chrome的JavaScript引擎是V8引擎,V8引擎具有极高的性能,能够快速解析和执行JavaScript代码,这使得Chrome在运行复杂JavaScript应用时表现出色。例如,在一些大型的JavaScript游戏、单页应用程序(SPA)中,V8引擎能够高效地处理大量的JavaScript逻辑,保证页面的流畅运行。
- FireFox:采用Gecko内核,Gecko内核具有良好的标准兼容性,对HTML、CSS和JavaScript等Web标准的支持较为全面。其JavaScript引擎是SpiderMonkey,它在FireFox浏览器中负责解析和执行JavaScript代码,为用户提供丰富的交互体验。在一些需要严格遵循Web标准的网页浏览场景中,FireFox凭借Gecko内核能够准确地呈现页面效果。
- Safari:使用WebKit内核,WebKit内核以其高效的渲染性能和良好的跨平台性受到广泛应用。许多移动浏览器和桌面浏览器都基于WebKit内核进行开发。Safari的JavaScript引擎是JavaScriptCore,它在执行JavaScript代码时也具有较高的效率,能够满足日常网页浏览和一些简单Web应用的需求。例如,在iOS设备上的Safari浏览器,利用WebKit内核和JavaScriptCore引擎,为用户提供了流畅的网页浏览体验。
- Edge:最初使用EdgeHTML内核,后来随着Chromium项目的发展,Edge切换到了基于Chromium的Blink内核,以获得更好的兼容性和性能。在JavaScript引擎方面,早期使用Chakra引擎,切换内核后也采用了与Chrome相同的V8引擎。这使得Edge在浏览现代网页时能够更好地支持各种新的Web技术和功能。
- IE:使用Trident内核,在过去相当长的一段时间内,IE浏览器在市场上占据重要地位,Trident内核也被广泛应用。然而,随着Web技术的不断发展,Trident内核在标准兼容性和性能方面逐渐暴露出一些问题。其JavaScript引擎在不同版本中有不同的实现,如IE3.0 - IE8.0使用JScript。在现代Web开发中,由于对新的Web标准支持不足,基于Trident内核的IE浏览器在浏览一些复杂网页时可能会出现显示异常或功能缺失的情况。
- Opera:经历了从Presto内核到Blink内核的转变。Presto内核在早期具有独特的优势,如快速的渲染速度和对一些Web标准的创新支持。但随着Web技术的发展,为了更好地与其他主流浏览器保持兼容性,Opera切换到了Blink内核。在JavaScript引擎方面,Opera在不同阶段使用了多种引擎,如Linear A、Linear B、Futhark、Carakan等。切换到Blink内核后,其JavaScript执行性能也得到了进一步提升。
- Node.js:虽然不是传统意义上的浏览器,但它同样使用V8引擎来执行JavaScript代码。Node.js使得JavaScript能够在服务器端运行,利用V8引擎的高性能,Node.js在构建高效的网络应用、后端服务等方面具有很大的优势。例如,许多基于Node.js开发的Web服务器框架,如Express,能够利用V8引擎快速处理大量的HTTP请求,实现高效的服务器端应用。
三、浏览器从输入url到呈现发生了什么
- 输入URL:用户在浏览器的地址栏中输入网址,例如www.example.com。此时,浏览器首先会对输入的内容进行检查,判断其是否符合URL的格式规范。如果输入的不是一个合法的URL,浏览器可能会尝试使用默认的搜索引擎对输入内容进行搜索。
- DNS解析:浏览器需要将输入的域名(如www.example.com)解析为对应的IP地址,因为在网络通信中,数据是通过IP地址进行传输的。DNS解析过程如下:
- 浏览器首先会在自己的DNS缓存中查找该域名对应的IP地址。如果缓存中存在该记录,并且缓存未过期,浏览器将直接使用缓存中的IP地址,从而加快访问速度。例如,用户经常访问的网站,其域名与IP地址的映射关系可能已经被缓存到浏览器中。
- 如果浏览器缓存中没有找到对应的IP地址,它会向操作系统的DNS缓存发起查询。操作系统也会维护一个DNS缓存,存储近期解析过的域名和IP地址映射。
- 如果操作系统的DNS缓存中也没有命中,浏览器会向本地配置的DNS服务器发送查询请求。本地DNS服务器通常由用户的网络服务提供商(ISP)提供,它可能会有自己的缓存,如果在缓存中找到匹配的记录,就返回给浏览器。
- 如果本地DNS服务器缓存中也没有找到,本地DNS服务器会按照一定的递归查询策略,向根域名服务器、顶级域名服务器、权威域名服务器等逐级查询,直到找到该域名对应的IP地址,并将其返回给浏览器。DNS解析是一个耗时的过程,如果解析域名过多,会导致网页首屏加载速度变慢。
- 建立TCP连接:在获取到目标服务器的IP地址后,浏览器会与服务器建立TCP连接。TCP连接的建立通过三次握手完成:
- 第一次握手:客户端(浏览器)向服务器发送一个SYN(同步序列编号)包,该包中包含客户端随机生成的一个初始序列号(ISN),此时客户端进入SYN_SENT状态,等待服务器的确认。
- 第二次握手:服务器接收到客户端的SYN包后,向客户端发送一个SYN + ACK包。这个包中包含服务器生成的初始序列号,同时对客户端的SYN包进行确认(ACK),确认号为客户端的序列号加1。此时服务器进入SYN_RECV状态。
- 第三次握手:客户端接收到服务器的SYN + ACK包后,向服务器发送一个ACK包,确认号为服务器的序列号加1。至此,客户端和服务器都进入ESTABLISHED状态,TCP连接建立成功。在同一个域名下,浏览器最多能够同时建立6个TCP连接,超过6个的请求会排队等待。
- 发送HTTP请求:TCP连接建立成功后,浏览器会向服务器发送HTTP请求。完整的HTTP请求报文包括以下部分:
- 请求行:包含请求方法(如GET、POST、PUT、DELETE等)、请求的URL以及使用的HTTP协议版本(如HTTP/1.1、HTTP/2等)。例如,一个GET请求的请求行可能是“GET /index.html HTTP/1.1”。
- 请求头:由一系列的键值对组成,用于向服务器传递一些附加信息,如浏览器的类型和版本(User - Agent)、客户端支持的语言(Accept - Language)、是否接受压缩(Accept - Encoding)、请求的来源(Origin)等。例如,“User - Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36”表示这是一个来自Windows 10系统、使用Chrome浏览器的请求。
- 空行:用于分隔请求头和请求体。
- 请求体:在GET请求中,请求体通常为空。而在POST、PUT等请求方法中,请求体用于携带需要发送到服务器的数据,如表单数据、JSON格式的数据等。例如,在一个用户注册的POST请求中,请求体可能包含用户输入的用户名、密码、邮箱等信息。
- 服务器处理请求并返回响应:服务器接收到浏览器的HTTP请求后,会对请求进行处理。服务器首先解析请求行和请求头,了解客户端的请求意图和相关信息。然后,根据请求的URL,服务器查找对应的资源文件,并根据请求方法(如GET表示获取资源,POST可能表示提交数据等)进行相应的处理。例如,如果是一个动态网页请求,服务器可能会调用相关的应用程序逻辑,查询数据库,生成动态内容。处理完成后,服务器会向浏览器返回HTTP响应。HTTP响应报文也包含多个部分:
- 状态行:包含HTTP协议版本、状态码以及状态码的描述。常见的状态码有200(表示请求成功)、301(永久重定向)、302(临时重定向)、404(资源未找到)、500(服务器内部错误)等。例如,“HTTP/1.1 200 OK”表示服务器成功处理了请求。
- 响应头:同样由一系列键值对组成,用于向客户端传递一些信息,如响应内容的类型(Content - Type,如text/html表示HTML页面,application/json表示JSON数据)、响应内容的长度(Content - Length)、缓存相关的信息(如Cache - Control、Expires)、跨域相关的信息(Access - Control - Allow - Origin)等。例如,“Content - Type: text/html; charset=UTF - 8”表示响应内容是HTML格式,字符编码为UTF - 8。
- 空行:分隔响应头和响应体。
- 响应体:包含服务器返回给客户端的实际数据,如HTML页面的内容、图片数据、JSON格式的数据等。如果请求的是一个HTML页面,响应体中就是该HTML页面的代码。
- 浏览器接收响应并解析渲染:
- 浏览器接收到服务器返回的HTTP响应后,首先解析响应头。根据响应头中的信息,浏览器可以进行一些操作,如根据Content - Type判断响应内容的类型,以便正确处理数据;根据缓存相关的头信息(Cache - Control、Expires等)决定是否使用缓存等。
- 如果响应内容是HTML页面,浏览器开始解析HTML代码,构建DOM树。在解析HTML的过程中,遇到CSS链接(如
<link rel="stylesheet" href="styles.css">),浏览器会发起新的HTTP请求获取CSS文件,并同时解析CSS构建CSSOM树。当CSSOM树构建完成后,浏览器将DOM树和CSSOM树合并成渲染树(Render Tree)。渲染树只包含需要显示在页面上的节点,如<script>标签、<meta>标签等不会出现在渲染树中。 - 在构建渲染树的过程中,如果遇到
<script>标签,浏览器会暂停文档的解析,优先下载并执行JavaScript脚本。因为JavaScript可能会修改DOM结构和CSS样式,如果不先执行JavaScript,可能会导致渲染结果不准确。这也是为什么在实际开发中,通常建议将JavaScript脚本放在页面底部或者使用异步加载(如<script async src="script.js"></script>)的方式,以避免阻塞页面的解析和渲染。 - 浏览器根据渲染树计算每个节点在屏幕上的大小、位置等布局信息(Layout)。在这个过程中,如果页面元素的布局发生变化(如元素的尺寸、位置改变),会触发回流(Reflow),回流会导致浏览器重新计算布局。同时,如果元素的样式发生改变(如颜色、背景色等不影响布局的属性改变),会触发重绘(Repaint)。回流通常比重绘更消耗性能,因为回流可能会导致一系列相关元素的布局重新计算。
- 最后,浏览器将计算好的布局信息交给绘图引擎,通过GPU加速将像素绘制(Paint)到屏幕上,最终呈现出用户看到的网页页面。
- 关闭TCP连接:当页面加载完成,数据传输结束后,浏览器和服务器之间的TCP连接可以关闭。TCP连接的关闭通过四次挥手完成:
- 第一次挥手:客户端(浏览器)向服务器发送一个FIN(结束标志)包,表示客户端不再发送数据,但还可以接收服务器的数据,此时客户端进入FIN_WAIT_1状态。
- 第二次挥手:服务器接收到客户端的FIN包后,向客户端发送一个ACK包,确认收到客户端的FIN包,此时服务器进入CLOSE_WAIT状态。客户端收到服务器的ACK包后,进入FIN_WAIT_2状态。
- 第三次挥手:服务器处理完剩余的数据后,向客户端发送一个FIN包,表示服务器也不再发送数据,此时服务器进入LAST_ACK状态。
- 第四次挥手:客户端接收到服务器的FIN包后,向服务器发送一个ACK包,确认收到服务器的FIN包,此时客户端进入TIME_WAIT状态。经过一段时间(通常为2倍的MSL,即最长报文段寿命)后,客户端进入CLOSED状态,服务器在收到客户端的ACK包后也立即进入CLOSED状态,TCP连接彻底关闭。
四、CSS加载会造成阻塞吗
- CSS不会阻塞DOM解析:在浏览器渲染过程中,DOM树和CSSOM树通常是并行构建的。浏览器在解析HTML文档时,会逐步构建DOM树,同时,如果遇到CSS链接(如
<link rel="stylesheet" href="styles.css">),会发起异步请求获取CSS文件,并在后台解析CSS构建CSSOM树,这个过程不会阻塞DOM的解析。这是因为DOM的解析主要是对HTML结构的分析和构建,与CSS的样式解析相对独立。例如,一个HTML页面中包含大量的文本内容和一些CSS链接,浏览器会先快速解析HTML文本构建DOM树,同时在后台加载和解析CSS,两者互不干扰。 - CSS会阻塞DOM渲染:由于渲染树(Render Tree)的构建依赖于DOM树和CSSOM树,只有当DOM树和CSSOM树都构建完成后,浏览器才能将它们合并成渲染树,并开始进行布局和绘制操作,从而显示页面内容。所以,如果CSS文件加载缓慢或者解析出现问题,会导致CSSOM树无法及时构建完成,进而阻塞DOM的渲染,使得
浏览器,面试题目,答案解析,前端开发,JavaScript, 渲染机制,缓存策略,跨域请求,Cookie,SameSite 属性,内存泄漏,HTTP/2,Service Worker,DevTools, 安全沙箱
资源地址: pan.quark.cn/s/50438c9ee…