2023前端面试记录-3

245 阅读11分钟

前言

今年的前端行情着实不太好。在面试太少的情况下,把握住每次面试机会,巩固一下过往的旧知识【是的,翻来覆去】

半个月都没有面试啦!5月15号到5月31日,一个都没有! 5月就这么结束了!!!

卷 + 少hc + 要求高 = [0] Offer

面试题如下

多个公司的面试题融合,不分公司!!!

问题:浏览器上输入url的过程

答案:

1、解析URL:首先会对 URL 进行解析,分析所需要使用的传输协议和请求的资源的路径。如果输入的 URL 中的协议或者主机名不合法,将会把地址栏中输入的内容传递给搜索引擎。如果没有问题,浏览器会检查 URL 中是否出现了非法字符,如果存在非法字符,则对非法字符进行转义后再进行下一过程。

2、缓存判断:浏览器会判断所请求的资源是否在缓存里,如果请求的资源在缓存里并且没有失效,那么就直接使用,否则向服务器发起新的请求。

3、DNS解析: 下一步首先需要获取的是输入的 URL 中的域名的 IP 地址,首先会判断本地是否有该域名的 IP 地址的缓存,如果有则使用,如果没有则向本地 DNS 服务器发起请求。本地 DNS 服务器也会先检查是否存在缓存,如果没有就会先向根域名服务器发起请求,获得负责的顶级域名服务器的地址后,再向顶级域名服务器请求,然后获得负责的权威域名服务器的地址后,再向权威域名服务器发起请求,最终获得域名的 IP 地址后,本地 DNS 服务器再将这个 IP 地址返回给请求的用户。用户向本地 DNS 服务器发起请求属于递归请求,本地 DNS 服务器向各级域名服务器发起请求属于迭代请求。

4、获取MAC地址: 当浏览器得到 IP 地址后,数据传输还需要知道目的主机 MAC 地址,因为应用层下发数据给传输层,TCP 协议会指定源端口号和目的端口号,然后下发给网络层。网络层会将本机地址作为源地址,获取的 IP 地址作为目的地址。然后将下发给数据链路层,数据链路层的发送需要加入通信双方的 MAC 地址,本机的 MAC 地址作为源 MAC 地址,目的 MAC 地址需要分情况处理。通过将 IP 地址与本机的子网掩码相与,可以判断是否与请求主机在同一个子网里,如果在同一个子网里,可以使用 APR 协议获取到目的主机的 MAC 地址,如果不在一个子网里,那么请求应该转发给网关,由它代为转发,此时同样可以通过 ARP 协议来获取网关的 MAC 地址,此时目的主机的 MAC 地址应该为网关的地址。

5、TCP三次握手: 下面是 TCP 建立连接的三次握手的过程,首先客户端向服务器发送一个 SYN 连接请求报文段和一个随机序号,服务端接收到请求后向客户端发送一个 SYN ACK报文段,确认连接请求,并且也向客户端发送一个随机序号。客户端接收服务器的确认应答后,进入连接建立的状态,同时向服务器也发送一个ACK 确认报文段,服务器端接收到确认后,也进入连接建立状态,此时双方的连接就建立起来了。

6、HTTPS握手: 如果使用的是 HTTPS 协议,在通信前还存在 TLS 的一个四次握手的过程。首先由客户端向服务器端发送使用的协议的版本号、一个随机数和可以使用的加密方法。服务器端收到后,确认加密的方法,也向客户端发送一个随机数和自己的数字证书。客户端收到后,首先检查数字证书是否有效,如果有效,则再生成一个随机数,并使用证书中的公钥对随机数加密,然后发送给服务器端,并且还会提供一个前面所有内容的 hash 值供服务器端检验。服务器端接收后,使用自己的私钥对数据解密,同时向客户端发送一个前面所有内容的 hash 值供客户端检验。这个时候双方都有了三个随机数,按照之前所约定的加密方法,使用这三个随机数生成一把秘钥,以后双方通信前,就使用这个秘钥对数据进行加密后再传输。

7、返回数据: 当页面请求发送到服务器端后,服务器端会返回一个 html 文件作为响应,浏览器接收到响应后,开始对 html 文件进行解析,开始页面的渲染过程。

8、页面渲染: 浏览器首先会根据 html 文件构建 DOM 树,根据解析到的 css 文件构建 CSSOM 树,如果遇到 script 标签,则判端是否含有 defer 或者 async 属性,要不然 script 的加载和执行会造成页面的渲染的阻塞。当 DOM 树和 CSSOM 树建立好后,根据它们来构建渲染树。渲染树构建好后,会根据渲染树来进行布局。布局完成后,最后使用浏览器的 UI 接口对页面进行绘制。这个时候整个页面就显示出来了。

9、TCP四次挥手: 最后一步是 TCP 断开连接的四次挥手过程。若客户端认为数据发送完成,则它需要向服务端发送连接释放请求。服务端收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入 CLOSE_WAIT 状态,此时表明客户端到服务端的连接已经释放,不再接收客户端发的数据了。但是因为 TCP 连接是双向的,所以服务端仍旧可以发送数据给客户端。服务端如果此时还有没发完的数据会继续发送,完毕后会向客户端发送连接释放请求,然后服务端便进入 LAST-ACK 状态。客户端收到释放请求后,向服务端发送确认应答,此时客户端进入 TIME-WAIT 状态。该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有服务端的重发请求的话,就进入 CLOSED 状态。当服务端收到确认应答后,也便进入 CLOSED 状态。

追问:浏览器的渲染过程

答案:

  1. 解析HTML Source,生成DOM树
  2. 解析css,生成cssom树
  3. 将dom树和cssom树结合,去除不可见元素,生成渲染树(Render Tree)
  4. layout(布局)根据生成的渲染树,进行布局,得到节点的几何信息(宽度、高度、位置等)
  5. Painting(重绘)根据渲染树以及回流得到的几何信息,将Render Tree 的每个像素渲染到屏幕上

image.png

追问:说一下重绘重排,怎么减少?

答案:

  • 重绘

    通过构造渲染树和回流阶段,知道了哪些节点是可见的,以及可见节点的样式和具体的几何信息(位置,大小),那么我们就可以将渲染树的每个节点都转换为屏幕上的实际像素,这个过程就叫做重绘。

    • 触发
      • 元素的样式发生变动,但是位置没有改变。(发生在 Paint 阶段)
  • 重排(回流)

    渲染对象在创建完成并添加到渲染树时,只是将DOM节点和它对应的样式结合起来,并不包含位置和大小信息,所以还需要layout这一过程计算它们的位置和大小

    • 触发

      • 元素的位置发生变动时发生重排,也叫回流(发生在layout阶段)
      • 页面首次渲染
      • 浏览器窗口大小发生改变resize
  • 减少触发

    • 避免使用 table 布局
    • 为元素提前设置好高宽,不因多次渲染改变位置
    • 减少直接操作dom元素,改用className用于控制
    • 批量添加删除dom节点
    • 使用定位改变,可减少重绘

重排必导致重绘

追问:说一下浏览器缓存

答案:

强缓存优先于协商缓存,强缓存生效则使用强缓存,若强缓存失败,则进行协商缓存

协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回304,继续使用缓存

  • 强缓存 image.png

    • 答案关键点
      • 强缓存优先于协商缓存
      • expires
      • cache-control
  • 协商缓存

    • 答案关键点
      • 304 / 200
      • Etag
      • last-modified

追问:301 302 304 403 503

答案:

  • 301 永久重定向,表示请求的资源已经被分配了新的URI
  • 302 临时重定向,希望用户使用新的URI访问资源,但只是临时性质,将来还可能发生改变
  • 304 协商缓存表示客户端发送附带条件的请求时,服务器端允许请求访问资源,但条件未满足
  • 403 Forbidden (禁止访问) 禁止访问
  • 503 (服务器无法使用) 服务器暂时无法处理请求(过载或者维护)

追问:说一下浏览器存储

答案:

  • cookie,localStorage,sessionStorage的区别

    • cookie可设置失效时间,默认为关闭浏览器后失效,sessionStorage仅在当前网页会话下有效,关闭页面或浏览器后就会被清除,localStorage除非手动清除,否则永久有效

    • cookie大小在4K以内,sessionStorage和localStorage大小在5M以内

    • 在进行请求时,cookie与服务器有关系,sessionStorage和localStorage仅在浏览器中保存

    • 从安全性来说,cookie安全性较低,所以一般不用来保存敏感信息,其他两个似乎也不安全。

    • cookie区分域,不区分端口,同ip下的不同端口cookie是共享的,sessionStorage和localStorage不可共享

  • 应用场景:

    • cookie可以用于识别用户登录
    • sessionStorage可用来保存一些临时的数据,防止用户刷新页面之后丢失了一些参数
    • localStorage可以用来传递在页面传递参数

问题:Object.prototype.toString.call()中toString原理

答案:

  1. 为什么需要call

    • 由于Object.prototype.toString()本身允许被修改,像Array、Boolean、Number的toString就被重写过,所以需要调用Object.prototype.toString.call(arg)来判断arg的类型,call将arg的上下文指向Object,所以arg执行了Object的toString方法。
  2. 为什么需要Object.prototype?

    • Object对象本身就有一个toString()方法,返回的是当前对象的字符串形式,原型上的toString()返回的才是我们真正需要的包含对象数据类型的字符串

问题:async await、promise、generator 谈谈区别

答案:

  • 答案关键点
    • promise
      • 三个状态,且不可逆转
      • then链式调用
      • 解决了ajax的回调地狱
      • 但是无法取消
      • 无法知道进行到什么阶段
    • async await
      • 同步形式
      • 解决promise的回调
      • 但是解决异常不太方便
      • generator的语法糖
    • generator
      • 是ES6提供的一种异步编程解决方案
      • 关键字yeild : function * ge(){ yeild x }
      • next()

追问:async await 返回什么? 怎么实现的? 怎么处理异常?

答案:

  • 返回
    1. async 函数返回一个 Promise 对象,可以接then方法。
    2. await后面接一个会return new promise的函数并执行它
  • 实现
    • async/await 就是 Generator 的语法糖,使得异步操作变得更加方便
  • 如何处理异常
    1. try cache
    2. 利用promise的cache提取一个工具函数
        function awaitWraper(promise) {
          return promise.then((res) => [null, res])
          .catch((err) => [err, null])
        }
        window.onload = async () => {
          let res = await awaitWraper(getData(3))
          console.log(res) // ["getdata error",null]
        }
    

追问:写一下实现步骤(在网上找到了原型题),解释一下为啥

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
 
async function async2() {
    console.log('async2');
}
 
console.log('script start');
 
setTimeout(()=>{
    console.log('setTimeout');
},0)
 
async1();
 
new Promise((resolve)=>{
    console.log('promise1');
    resolve();
}).then(()=>{
    console.log('promise2');
});
 
console.log('script end');

答案:

image.png

追问:解释下宏任务,微任务

  • macrotask[宏任务]

    • setTimeout
    • setInterval
    • setImmediate(Node独有)
    • requestAnimationFrame(浏览器独有)
    • I/O
    • UI rendering(浏览器独有)
  • microTask[微任务]

    • process.nextTick(Node 独有)
    • Promise
    • Object.observe
    • MutationObserver

答案: