Zong
面经大挑战

假期回来忙着单位的新项目,也抽出空余的时间,借着这个机会对面经进行学习。

说是大挑战其实也算不上,其实就是借助 P手 整理的面试题以及面试经验进行学习啦。

为什么要学习这个呢,一是为了学习基础,二是从此扩充自己的知识面,看看有没有什么新的启发,当然现在暂时还没有。

经过学习,收获颇多,但是因为大佬们都总结的很充分,我暂时也没有新的感触,我就此简单做个总结(做个搬水工):

完整的面经,请参阅仓库sosohime/interview

当用户在浏览器输入地址按下回车键后发生了什么?

  1. 回车键按下
  2. 解析 URL
  3. 检查 HSTS 列表
  4. DNS 查询
  5. ARP 过程
  6. 使用套接字
  7. TLS 握手
  8. HTTP 协议
  9. HTTP 服务器请求处理
  10. HTML 解析
  11. CSS 解析
  12. 页面渲染
  13. GPU 渲染

HTTP 状态码

  • 1XX:相关信息
  • 2XX:操作成功
    • 200 请求已成功,请求所希望的响应头或数据体将随此响应返回。
    • 201 请求已经被实现,而且有一个新的资源已经依据请求的需要而建立,且其 URI 已经随 Location 头信息返回。
    • 202 服务器已接受请求,但尚未处理。
    • 204 服务器成功处理了请求,但不需要返回任何实体内容,并且希望返回更新了的元信息。
  • 3XX:重定向
    • 301 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。
    • 302 请求的资源现在临时从不同的 URI 响应请求。
    • 303 对应当前请求的响应可以在另一个 URI 上被找到,而且客户端应当采用 GET 的方式访问那个资源。
    • 307 请求的资源现在临时从不同的 URI 响应请求。
  • 4XX:客户端错误
    • 400 语义有误,当前请求无法被服务器理解,或请求参数有误。
    • 401 当前请求需要用户验证。
    • 403 服务器已经理解请求,但是拒绝执行它。
    • 404 请求失败,请求所希望得到的资源未被在服务器上发现。
    • 405 请求行中指定的请求方法不能被用于请求相应的资源。
    • 410 被请求的资源在服务器上已经不再可用,而且没有任何已知的转发地址。
    • 415 对于当前请求的方法和所请求的资源,请求中提交的实体并不是服务器中所支持的格式,因此请求被拒绝。
    • 422 请求格式正确,但是由于含有语义错误,无法响应。
    • 429 请求次数超过限额。
  • 5XX:服务器错误
    • 500 服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。
    • 503 由于临时的服务器维护或者过载,服务器当前无法处理请求。

利用 HTTP Headers 实现浏览器缓存

强制缓存优先于协商缓存进行,若强制缓存( Expires 和 Cache-Control )生效则直接使用缓存,若不生效则进行协商缓存( Last-Modified / If-Modified-Since 和 Etag / If-None-Match ),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回 304 ,继续使用缓存,主要过程如下:

pic-1

强制缓存

  • Expires 指定一个日期 / 时间,超过该时间则认为此回应已经过期。
  • Cache-Control 用来指定当前的请求 / 回复中的,是否使用缓存机制。

注:在无法确定客户端的时间是否与服务端的时间同步的情况下, Cache-Control 相比于 Expires 是更好的选择,所以同时存在时,只有 Cache-Control 生效。

协商缓存

  • Last-Modified 所请求的对象的最后修改日期(按照 RFC 7231 中定义的“超文本传输协议日期”格式来表示)。
  • If-Modified-Since 允许在对应的资源未被修改的情况下返回 304 未修改。
  • Etag 对于某个资源的某个特定版本的一个标识符,通常是一个消息散列。
  • If-None-Match 允许在对应的内容未被修改的情况下返回 304 未修改( 304 Not Modified ),参考“超文本传输协议”的实体标记。

注: Etag / If-None-Match 优先级高于 Last-Modified / If-Modified-Since ,同时存在则只有 Etag / If-None-Match 生效。

CSS 加载会造成阻塞吗?

  • CSS 加载不会阻塞 DOM 树的解析
  • CSS 加载会阻塞 DOM 树的渲染
  • CSS 加载会阻塞后面 JavaScript 执行

因此,为了避免让用户看到长时间的白屏时间,我们应该尽可能的提高 CSS 加载速度,比如可以使用以下几种方法:

  1. 使用 CDN (因为 CDN 会根据你的网络状况,替你挑选最近的一个具有缓存内容的节点为你提供资源,因此可以减少加载时间)。
  2. 对 CSS 进行压缩(可以用很多打包工具,比如 webpack, gulp 等,也可以通过开启 gzip 压缩)。
  3. 合理的使用缓存(设置 Cache-Control, Expires, 以及 Etag 都是不错的,不过要注意一个问题,就是文件更新后,你要避免缓存而带来的影响。其中一个解决防范是在文件名字后面加一个版本号)。
  4. 减少 HTTP 请求数,将多个 CSS 文件合并,或者是干脆直接写成内联样式(内联样式的一个缺点就是不能缓存)。

JavaScript 继承 面试题解答

// 用 ES5 和 ES6 分别实现继承:
// Animal 具有 getType、getName 方法
// Cat 继承于 Animal

const animal = new Animal()
animal.getType() // I am Animal
animal.getName() // I don't know

const kitty = new Cat('Kitty')
kitty.getType() // I am Cat
kitty.getName() // My name is Kitty
// ES5 实现

const Animal = function () {}

Animal.prototype.getType = function () {
  console.log('I am Animal')
}

Animal.prototype.getName = function () {
  console.log('I don\'t know')
}

const Cat = function (name) {
  this.name = name
  this.getType = function () {
    console.log('I am Cat')
  }
  this.getName = function () {
    console.log('My name is '+ this.name)
  }
}

Cat.prototype = new Animal()
// ES6 实现

class Animal {
  getType () {
    console.log('I am Animal')
  }
  getName () {
    console.log('I don\'t know')
  }
}

class Cat extends Animal {
  constructor (name) {
    super()
    this.name = name
  }
  getType () {
    console.log('I am Cat')
  }
  getName () {
    console.log('My name is '+ this.name)
  }
}

React diff 策略

  • React 通过制定大胆的 diff 策略,将 复杂度的问题转换成 复杂度的问题。
  • React 通过分层求异的策略,对 tree diff 进行算法优化。
  • React 通过相同类生成相似树形结构,不同类生成不同树形结构的策略,对 component diff 进行算法优化。
  • React 通过设置唯一 key 的策略,对 element diff 进行算法优化。
  • 建议,在开发组件时,保持稳定的 DOM 结构会有助于性能的提升。
  • 建议,在开发过程中,尽量减少类似将最后一个节点移动到列表首部的操作,当节点数量过大或更新操作过于频繁时,在一定程度上会影响 React 的渲染性能。

相关链接