前端面试官-一问到底系列

2,844 阅读19分钟

前言

最近忙着做面试官,出一期我的面试官思路,面试时长我一般控制在半小时左右,大家时间都很宝贵;

我认为面试别人何尝不是一次难得的学习机会;

对于面试者来说,哪怕不能让他“听君一席话,胜读十年书”;也要让他感叹不虚此行,学到了;

对于面试官来说,每次当我问出一个问题,我也会思考我会怎么答;这也是“学而时习之,温故而知新”的过程,厚积定能薄发,每次对相同的知识亦或者问题都有不一样的心得,不一样的思考,亦有所得。

针对不一样的人出不一样的题,遇强则强,遇弱则降低点难度,多一点引导,少一点对错,多一点反馈,少一点沉默。

遇到基础稍微差点的,答不上来,我会以引导为主,只要愿意思考,我会帮他构建知识基础,由点到线,由线到面。

遇到基础好,有一定沉淀的人,我会以学习交流为主,把这一次面试当成一种多样化知识蓝图的构建点,同时对等输出我的产出

面试遇到过各种各样的面试者,他们各有特色,有不自信的,有自卑的,有自傲的,有爱抬杠的......形形色色,这也正折射着当下所谓的“前端已死”、“环境差”等名词;有趣的是一部分人口口声声把这些东西来作为自己“菜”的借口,遇到不会的的问题,说一句我看过来着,一紧张忘了,记不清了。

环境一直都在变,人也一直在变。但是有个规则是不变的:实力为尊。认清自己,找到定位,思考破局。

最后我都会让面试者进行提问,其中也有实诚人,说:“面试官谢谢你的面试,虽然我发挥的不太好,但是很幸运你,让我获益匪浅,面试官能不能给我一点指点”;我自会道出一二建议。

祭品说,精神反刍和吸引力法则,你信奉什么主义,就会化作什么祭品。你信奉环境差,你何尝不是祭品

下面开始本次的一问到底

在浏览器输入URL后,回车发生了什么

先来个总流程图,然后进入我的知识点一问到底环节

image.png

1、解析什么?

浏览器首先对 URL 解析,解析出协议、域名、端口、资源路径、参数等。

2、DNS 域名解析展开讲讲?

DNS 全称 Domain Name System , 即域名系统。

接触过服务器亦或者你本地启项目IP地址可以观察下,就会发现服务器地址通常是一串数字,例如192.168.

那么通常我们输入的网址,显然不是IP地址,所以肯定会有一个解析过程,也就是DNS解析。

一般而言,域名比IP地址更好记,因而我们更习惯在浏览器输入域名而不是 IP,而计算机网络通信所识别的计算机标识是 IP 地址,因而首先需要将一个域名转化为相应的IP地址,这就是 DNS 协议所要做的事。

DNS 就像我们手机中的通讯录一样,通讯录中备注的是对方的姓名(类似于域名),但是打电话的时候实际需要的是电话号码(类似于 IP 地址),利用通讯录将一个姓名转化为对应的电话号码。

image.png

2.1 解析完后为什么有些网址打开很快有些很慢?

这就涉及到强缓存和协商缓存,浏览器在加载资源时,会先根据本地缓存资源的 header 中的信息判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求。当强缓存没有命中的时候,浏览器会发送一个请求到服务器,服务器根据 header 中的部分信息来判断是否命中缓存(协商缓存)。如果命中,则返回 304 ,告诉浏览器资源未更新,可使用本地的缓存。

强缓存

浏览器在加载资源时,会先根据本地缓存资源的 header 中的信息判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求。

  • 这里的 header 中的信息指的是 expires 和 cahe-control.
  • Expires 该字段是 http1.0 时的规范,它的值为一个绝对时间的 GMT 格式的时间字符串,比如 Expires:Mon,18 Oct 2066 23:59:59 GMT。这个时间代表着这个资源的失效时间,在此时间之前,即命中缓存。这种方式有一个明显的缺点,由于失效时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱(本地时间也可以随便更改)。
  • Cache-Control(优先级高于 Expires) Cache-Controlhttp1.1 时出现的 header 信息,主要是利用该字段的 max-age 值来进行判断,它是一个相对时间,例如 Cache-Control:max-age=3600,代表着资源的有效期是 3600 秒。cache-control 除了该字段外,还有下面几个比较常用的设置值:
  • no-cache:需要进行协商缓存,发送请求到服务器确认是否使用缓存。 no-store:禁止使用缓存,每一次都要重新请求数据。 public:可以被所有的用户缓存,包括终端用户和 CDN 等中间代理服务器。 private:只能被终端用户的浏览器缓存,不允许 CDN 等中继缓存服务器对其缓存。 Cache-ControlExpires 可以在服务端配置同时启用,同时启用的时候Cache-Control优先级高。

协商缓存

当强缓存没有命中的时候,浏览器会发送一个请求到服务器,服务器根据 header 中的部分信息来判断是否命中缓存。如果命中,则返回 304 ,告诉浏览器资源未更新,可使用本地的缓存。

  • 这里的 header 中的信息指的是 Last-Modify/If-Modify-Since 和 ETag/If-None-Match.
  • Last-Modify/If-Modify-Since 浏览器第一次请求一个资源的时候,服务器返回的 header 中会加上 Last-Modify,Last-modify 是一个时间标识该资源的最后修改时间(只能精确到秒,所以间隔时间小于 1 秒的请求是检测不到文件更改的。)。
  • 当浏览器再次请求该资源时,request 的请求头中会包含 If-Modify-Since,该值为缓存之前返回的 Last-Modify。服务器收到 If-Modify-Since 后,根据资源的最后修改时间判断是否命中缓存。 ​ 如果命中缓存,则返回 304,并且不会返回资源内容,并且不会返回 Last-Modify
  • 缺点: 短时间内资源发生了改变,Last-Modified 并不会发生变化。
  • 周期性变化。如果这个资源在一个周期内修改回原来的样子了,我们认为是可以使用缓存的,但是Last-Modified可不这样认为, 因此便有了 ETag
  • ETag/If-None-Match Etag 是基于文件内容进行编码的,可以保证如果服务器有更新,一定会重新请求资源,但是编码需要付出额外的开销。
  • 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

3.建立 TCP 连接

一般在浏览器输入 URL,应用层的协议为 HTTP/HTTPS,其需要的是可靠的服务,所使用的传输层协议为 TCP

通过域名解析后,浏览器获得了服务器的 IP,则向服务器发起 TCP 连接,这时候就会发生三次握手行为。 image.png

3.1 OSI参考模型或七层模型是什么?

七层模型,亦称OSI(Open System Interconnection)。参考模型是国际标准化组织ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型。 它是一个七层的、抽象的模型体,不仅包括一系列抽象的术语或概念,也包括具体的协议。 image.png

应用层

网络服务与最终用户的一个接口。

协议有:HTTP FTP TFTP SMTP SNMP DNS TELNET HTTPS POP3 DHCP

表示层

数据的表示、安全、压缩。(在五层模型里面已经合并到了应用层)

格式有,JPEG、ASCll、EBCDIC、加密格式等 [2] 

会话层

建立、管理、终止会话。(在五层模型里面已经合并到了应用层)

对应主机进程,指本地主机与远程主机正在进行的会话

传输层

定义传输数据的协议端口号,以及流控和差错校验。

协议有:TCP UDP,数据包一旦离开网卡即进入网络传输层

网络层

进行逻辑地址寻址,实现不同网络之间的路径选择。

协议有:ICMP IGMP IP(IPV4 IPV6)

数据链路层

建立逻辑连接、进行硬件地址寻址、差错校验 等功能。(由底层网络定义协议)

将比特组合成字节进而组合成帧,用MAC地址访问介质,错误发现但不能纠正。

物理层

建立、维护、断开物理连接。(由底层网络定义协议)

TCP/IP 层级模型结构,应用层之间的协议通过逐级调用传输层(Transport layer)、网络层(Network Layer)和物理数据链路层(Physical Data Link)而可以实现应用层的应用程序通信互联。

应用层需要关心应用程序的逻辑细节,而不是数据在网络中的传输活动。应用层其下三层则处理真正的通信细节。在 Internet 整个发展过程中的所有思想和着重点都以一种称为 RFC(Request For Comments)的文档格式存在。针对每一种特定的 TCP/IP 应用,有相应的 RFC 文档。

3.2TCP/IP协议是什么?

TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议) 是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP协议不仅仅指的是TCP IP两个协议,而是指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇, 只是因为在TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。

它是在网络的使用中的最基本的通信协议。TCP/IP传输协议对互联网中各部分进行通信的标准和方法进行了规定。并且,TCP/IP传输协议是保证网络数据信息及时、完整传输的两个重要的协议。TCP/IP传输协议是严格来说是一个四层的体系结构,应用层、传输层、网络层和数据链路层都包含其中。

3.3 TCP/IP协议有哪些特点?

TCP/IP协议能够迅速发展起来并成为事实上的标准,是它恰好适应了世界范围内数据通信的需要。它有以下特点:

  • 协议标准是完全开放的,可以供用户免费使用,并且独立于特定的计算机硬件与操作系统。
  • 独立于网络硬件系统,可以运行在广域网,更适合于互联网。
  • 网络地址统一分配,网络中每一设备和终端都具有一个唯一地址。
  • 高层协议标准化,可以提供多种多样可靠网络服务。

3.4TCP/IP协议包含哪几层?

  1. 应用层;
  2. 传输层;
  3. 网络层;
  4. 网络接口层。
  • 应用层位于TCP/IP协议的第一层,是直接为应用进程提供服务的;运输层位于协议的第二层,在整个TCP/IP协议中起到了中流砥柱的作用;网络层位于协议的第三层;网络接口层位于协议的第四层。

3.5讲讲三次握手四次挥手?

三次握手

  • 第一次握手 客户端向服务端发送连接请求报文段。该报文段的头部中 SYN=1,ACK=0,seq=x。请求发送后,客户端便进入 SYN-SENT 状态。
  • PS1:SYN=1,ACK=0表示该报文段为连接请求报文。 PS2:x 为本次 TCP 通信的字节流的初始序号。 TCP 规定:SYN=1 的报文段不能有数据部分,但要消耗掉一个序号。 第二次握手 服务端收到连接请求报文段后,如果同意连接,则会发送一个应答:SYN=1,ACK=1,seq=y,ack=x+1。 该应答发送完成后便进入 SYN-RCVD 状态。
  • PS1:SYN=1,ACK=1 表示该报文段为连接同意的应答报文。 PS2:seq=y 表示服务端作为发送者时,发送字节流的初始序号。 PS3:ack=x+1 表示服务端希望下一个数据报发送序号从x+1开始的字节。 第三次握手 当客户端收到连接同意的应答后,还要向服务端发送一个确认报文段,表示:服务端发来的连接同意应答已经成功收到。 该报文段的头部为:ACK=1,seq=x+1,ack=y+1。 客户端发完这个报文段后便进入 ESTABLISHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接的建立完成!

3.5.1为什么连接建立需要三次握手,而不是两次握手

  • 在谢希仁著《计算机网络》第四版中讲 “三次握手” 的目的是 “为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。在另一部经典的《计算机网络》一书中讲“三次握手” 的目的是为了解决 “网络中存在延迟的重复分组” 的问题。这两种不用的表述其实阐明的是同一个问题。

  • 谢希仁版《计算机网络》中的例子是这样的,“已失效的连接请求报文段”的产生在这样一种情况下:client 发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达 server。本来这是一个早已失效的报文段。但 server 收到此失效的连接请求报文段后,就误认为是 client 再次发出的一个新的连接请求。于是就向 client 发出确认报文段,同意建立连接。假设不采用 “三次握手”,那么只要 server 发出确认,新的连接就建立了。由于现在 client 并没有发出建立连接的请求,因此不会理睬 server 的确认,也不会向 server 发送数据。但 server 却以为新的运输连接已经建立,并一直等待 client 发来数据。这样,server 的很多资源就白白浪费掉了。采用“三次握手” 的办法可以防止上述现象发生。例如刚才那种情况,client 不会向 server 的确认发出确认。server 由于收不到确认,就知道 client 并没有要求建立连接。”

四次挥手 第一次挥手 若 A 认为数据发送完成,则它需要向 B 发送连接释放请求。该请求只有报文头,头中携带的主要参数为: FIN=1,seq=u。此时,A 将进入 FIN-WAIT-1 状态。

  • PS1:FIN=1 表示该报文段是一个连接释放请求。 PS2:seq=u,u-1 是 A 向 B 发送的最后一个字节的序号。 第二次挥手 B 收到连接释放请求后,会通知相应的应用程序,告诉它 A 向 B 这个方向的连接已经释放。此时 B 进入 CLOSE-WAIT 状态,并向 A 发送连接释放的应答,其报文头包含: ACK=1,seq=v,ack=u+1。
  • PS1:ACK=1:除 TCP 连接请求报文段以外,TCP 通信过程中所有数据报的 ACK 都为 1,表示应答。 PS2:seq=v,v-1 是 B 向 A 发送的最后一个字节的序号。 PS3:ack=u+1 表示希望收到从第 u+1 个字节开始的报文段,并且已经成功接收了前 u 个字节。 A 收到该应答,进入 FIN-WAIT-2 状态,等待 B 发送连接释放请求。
  • 第二次挥手完成后,A 到 B 方向的连接已经释放,B 不会再接收数据,A 也不会再发送数据。但 B 到 A 方向的连接仍然存在,B 可以继续向 A 发送数据。
  • 第三次挥手 当 B 向 A 发完所有数据后,向 A 发送连接释放请求,请求头:FIN=1,ACK=1,seq=w,ack=u+1。B 便进入 LAST-ACK 状态。
  • 第四次挥手 A 收到释放请求后,向 B 发送确认应答,此时 A 进入 TIME-WAIT 状态。该状态会持续 2MSL 时间,若该时间段内没有 B 的重发请求的话,就进入 CLOSED 状态,撤销 TCB。当 B 收到确认应答后,也便进入 CLOSED 状态,撤销 TCB。
  • 为什么 A 要先进入 TIME-WAIT 状态,等待 2MSL 时间后才进入 CLOSED 状态? 为了保证 B 能收到 A 的确认应答。 若 A 发完确认应答后直接进入 CLOSED 状态,那么如果该应答丢失,B 等待超时后就会重新发送连接释放请求,但此时 A 已经关闭了,不会作出任何响应,因此 B 永远无法正常关闭。

image.png

4. 浏览器解析渲染页面

浏览器收到服务器的响应报文后,从响应体中得到相应资源,如 HTML 文件、图片、视频等,并进行渲染,然后将结果呈现给用户。

4.1 讲讲页面渲染过程?

  • 解析HTML,
  • 构建DOM树  
  • 解析 CSS ,生成 CSS 规则树  
  • 合并 DOM 树和 CSS 规则,
  • 生成 render 树  
  • 布局 render 树( Layout / reflow ),
  • 负责各元素尺寸、位置的计算  绘制 render 树( paint ),绘制页面像素信息  浏览器会将各层的信息发送给 GPU,GPU 会将各层合成( composite ),显示在屏幕上

4.2讲讲重排和重绘?

一、重绘不一定需要重排,重排必然会导致重绘

1、重排:当渲染树的一部分必须更新并且节点的尺寸发生了变化,浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。

1)添加、删除可见的dom

2)元素的位置改变

3)元素的尺寸改变(外边距、内边距、边框厚度、宽高等几何属性)

4)页面渲染初始化

5)浏览器窗口尺寸改变

2、重绘:是在一个元素的外观被改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。

二、减少reflow、repaint

1、不要一条一条的修改DOM的样式,可以先定义好cssclass,然后修改DOMclassName

2、不要把DOM结点的属性值放在一个循环里当成循环里的变量。

3、为动画的HTML使用fixedabsoluteposition,那么修改他们的css是不会reflow

4.2打开 Chrome 浏览器一个页面,至少会出现几个进程?

最新的 Chrome 浏览器包括至少四个: 1 个浏览器(Browser)主进程、1 个 GPU 进程、1 个网络(NetWork)进程、多个渲染进程和多个插件进程, 当然还有复杂的情况;

  • 页面中有 iframe 的话, iframe会单独在进程中
  • 有插件的话,插件也会开启进程
  • 多个页面属于同一站点,并且从 a 打开 b 页面,会共用一个渲染进程
  • 装了扩展的话,扩展也会占用进程
  • 这些进程都可以通过 Chrome 任务管理器来查看

4.3即使如今多进程架构,还是会碰到单页面卡死的最终崩溃导致所有页面崩溃的情况,讲一讲你的理解?

提供一种情况,就是同一站点, 围绕这个展开也行。

  • Chrome 的默认策略是,每个标签对应一个渲染进程。但是如果从一个页面打开了新页面,而新页面和当前页面属于同一站点时,那么新页面会复用父页面的渲染进程。官方把这个默认策略叫 process-per-site-instance。
  • 更加简单的来说,就是如果多个页面符合同一站点,这几个页面会分配到一个渲染进程中去, 所以有这样子的一种情况, 一个页面崩溃了,会导致同一个站点的其他页面也奔溃,这是因为它们使用的是同一个渲染进程。
  • 有人会问为什么会跑到一个进程里面呢?
  • 你想一想呀, 属于同一家的站点,比如下面三个:

写在最后

其实就这一个问题的扩展还有很多,思维发散便可触类旁通,反向推导,由面到线,由线到点,大家有所见解可以留言评论区,比方说TCP和UDP报文的区别、浏览器内核相关知识、等等.....

我是凉城a,一个前端,热爱技术也热爱生活。

希望你读完我的文章,每次都有不一样的收获。

如果你想了解更多,请点这里,期待你的小⭐⭐

  • 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注😊
  • 本文首发于掘金,未经许可禁止转载💌