前端面试题目汇总

HTTP

  • HTTP 缓存机制

    • 基本原理

      1. 浏览器在加载资源时,根据请求头的expires和cache-control判断是否命中强缓存,是则直接从缓存读取资源,不会发请求到服务器。

      2. 如果没有命中强缓存,浏览器一定会发送一个请求到服务器,通过last-modified和etag验证资源是否命中协商缓存,如果命中,服务器会将这个请求返回,但是不会返回这个资源的数据,依然是从缓存中读取资源

      3. 如果前面两者都没有命中,直接从服务器加载资源

  • HTTP 强缓存协商缓存

    • 相同点

      如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据。

    • 不同点

      强缓存不发请求到服务器,协商缓存会发请求到服务器。

    • 强缓存

      1. Expires

        Expires 是http1.0提出的一个表示资源过期时间的header,它描述的是一个绝对时间,由服务器返回。Expires 受限于本地时间,如果修改了本地时间,可能会造成缓存失效

        1
        Expires: Wed, 11 May 2018 07:20:00 GMT
      2. Cache-Control

        Cache-Control 出现于 HTTP / 1.1,优先级高于 Expires ,表示的是相对时间

        1
        Cache-Control: max-age=315360000

        Cache-Control: no-cache 不会缓存数据到本地的说法是错误的,详情《HTTP权威指南》P182

        Cache-Control: no-store 才是真正的不缓存数据到本地

        Cache-Control: public 可以被所有用户缓存(多用户共享),包括终端和CDN等中间代理服务器

        Cache-Control: private 只能被终端浏览器缓存(而且是私有缓存),不允许中继缓存服务器进行缓存

    • 协商缓存

      当浏览器对某个资源的请求没有命中强缓存,就会发一个请求到服务器,验证协商缓存是否命中,如果协商缓存命中,请求响应返回的http状态为304并且会显示一个Not Modified的字符串。

      1. Last-ModifiedIf-Modified-Since

        Last-Modified 表示本地文件最后修改日期,浏览器会在request header加上If-Modified-Since(上次返回的 Last-Modified 的值),询问服务器在该日期后资源是否有更新,有更新的话就会将新的资源发送回来。

      2. ETagIf-None-Match

        Etag 就像一个指纹,资源变化都会导致ETag变化,跟最后修改时间没有关系,ETag可以保证每一个资源是唯一的

        If-None-Match 的header会将上次返回的Etag发送给服务器,询问该资源的Etag是否有更新,有变动就会发送新的资源回来。

      ETag的优先级比Last-Modified更高,
      具体为什么要用ETag,主要出于下面几种情况考虑:

      1. 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET
      2. 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒)
      3. 某些服务器不能精确的得到文件的最后修改时间
  • 介绍一下 HTTP/2 新增特性

    • 多路复用

      HTTP/2将一个TCP连接分为若干个流(Stream),每个流中可以传输若干消息(Message),每个消息由若干最小的二进制帧(Frame)组成。这也是HTTP/1.1与HTTP/2最大的区别所在。 HTTP/2中,每个用户的操作行为被分配了一个流编号(stream ID),这意味着用户与服务端之间创建了一个TCP通道;协议将每个请求分割为二进制的控制帧与数据帧部分,以便解析。

    • HPACK 算法

      HTTP/2 引入HPACK算法对HTTP头部做压缩。

    • 服务器推送

      服务器推送简单来说就是,还没有收到浏览器的请求,服务器就把各种资源推送给浏览器。

      比如,浏览器只请求了index.html,但是服务器把index.html、style.css、example.png全部发送给浏览器。这样的话,只需要一轮 HTTP 通信,浏览器就得到了全部资源,提高了性能。

JavaScript

  • 语言基础问题

    1. 下列代码运行后结果

      1
      2
      3
      4
      5
      6
      7
      var a = 2

      function a() {
      console.log('1')
      }

      a() // 1
    2. [1, 2, 3, 4, 5] 变成 [2, 3, 4, 5, 6] 都有哪些方式?

      1
      2
      3
      4
      5
      6
      7
      8
      9
      let arr = [1, 2, 3, 4, 5]

      arr = arr.map(item => item + 1)

      arr.forEach((item, index) => {
      arr[index] = arr[index] + 1 // 改变原数组
      })

      Array.form(arr, t => t + 1)
    3. 写出至少5种数组浅拷贝的方式

      1
      2
      3
      4
      5
      6
      7
      8
      let arr = [{a: 1}, {a: 2}, {a: 3}, {a: 4}, {a: 5}]

      const arr1 = [...arr]
      const arr2 = arr.concat()
      const arr3 = arr.map(item => item)
      const arr4 = Array.from(arr)
      const arr5 = arr.slice(0)
      const arr6 = JSON.parse(JSON.stringify(arr)) // 不安全的
    4. 哪些方法不会修改原数组,哪些方法会修改原数组

      1
      2
      3
      4
      // 会修改原数组的方法


      // 不会修改原数组的方法
    5. 如何判断变量类型

      1
      2
      3
      4
      5
      6
      7
      8
      9
      var val1 = null
      var val2
      var val3 = function() {
      console.log(111)
      }

      Object.prototype.toString.call(val1) // "[object Null]"
      Object.prototype.toString.call(val2) // "[object Undefined]"
      Object.prototype.toString.call(val3) // "[object Function]"
    6. 如何截取上面类型字符串

      1
      2
      3
      4
      let str = "[object Function]"
      console.log(str.slice(8, -1))

      str.match(/\[object\s(\w+)\]/)[1]