「每周前端面试题专栏」- 滴水之功,开拓大厂之路(第三周)

635 阅读14分钟

写在前面

充实的周末是不是要过完了呢~ 充点电吧兄弟。

建了一个公众号,每周周一 至 周五,每天发布若干道面试题,并奉上个人觉得还行的解答,周六或周天发一遍汇总~。

希望大家有所得,希望自己有所得。

下面是本周的汇总(2020.07.20 - 2020.07.24)。

目录

  1. 移动端适配 1px 的问题
  2. 实现格式化输出,比如输入 999999999,输出 999,999,999
  3. 介绍一下你对浏览器内核的理解
  4. 从输入 URL 到页面加载全过程
  5. 说一下 css3 的 animation
  6. 谈⼀谈箭头函数与普通函数的区别?
  7. BFC 是什么?触发 BFC 的条件是什么?有哪些应用场景?
  8. DNS 解析的具体过程
  9. React 中 setState 是同步的还是异步的
  10. 说一下 TCP 三次握手过程
  11. 说一下 TCP 四次挥手过程
  12. 绍一下对称加密和非对称加密
  13. 为什么 TCP 建立连接需要三次握手,而不是两次
  14. https 的握手过程
  15. React 组件通信如何实现

详情

一、移动端适配 1px 的问题

首先说下造成 1px 的边框在移动端上变粗的原因:

因为 css 中的 1px 并不等于移动设备的 1px,这是由于不同的的手机有不同的像素密度。在 window 对象中有一个 devicePixelRatio 属性,他可以反应 css 中的像素与设备的像素比。

devicePixelRatio 的官方定义为:设备物理像素和设备独立像素的比例

我了解的解决方法有四种,实际项目中灵活运行

  1. WWDC 对 IOS 的建议:直接使用 0.5px 边框

    缺点: 仅支持 IOS 8+,不支持安卓。

  2. 使用边框图片:border-image

    .border-image-1px {
      border1px solid transparent;
      border-imageurl('../img/hairline_gray.png'2 repeat;
    }

    优点:可以设置单条、多条边框
    缺点:修改颜色麻烦,圆角需要特殊处理

  3. 使用 box-shadow 模拟边框

    .box-shadow-1px {
      box-shadow: inset 0 -1px 1px -1px #e5e5e5;
    }

    优点:使用简单,圆角也可以实现
    缺点:边框有阴影,百分百过不了视觉走查

  4. 伪类 + transform + 绝对定位 实现

    .scale-1px {
      position: relative;
      &::after {
        content'';
        width100%;
        height1px/* no */
        background#e5e5e5;
        position: absolute;
        left0;
        bottom0;
        transformscaleY(0.5);
      }
    }

    优点:所有场景都能满足,支持圆角
    缺点:伪类冲突 - -

二、实现格式化输出,比如输入 999999999,输出 999,999,999

function formatNum(num{
  return num..replace(/\d{1,3}(?=(\d{3})+$)/g'$&,');
}

三、介绍一下你对浏览器内核的理解

主要分成两部分:渲染引擎(layout engineerRendering Engine)和 JS 引擎

渲染引擎:负责取得网页的内容(HTMLXML、图像等等)、整理讯息(例如加入 CSS 等),以及计算网页的显示方式,然后会输出至显示器。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。所有网页浏览器、移动端、客户端等显示网络内容的应用程序都需要内核

JS 引擎:解释和执行 javascript 来实现网页的动态效果

最开始渲染引擎和 JS 引擎并没有区分的很明确,后来 JS 引擎越来越独立,内核就倾向于只指渲染引擎。

四、从输入 URL 到页面加载全过程

这题算是前端基础领域的一道大题了,考点不在于难度,而是这题可以延展出很多知识点,这里只记录主流程。

顺便说一句,这道题可以用来作为自己知识库的一条主脉。

  1. 从浏览器接收 url 到开启网络请求线程(这一部分可以展开浏览器的机制以及进程与线程之间的关系)

  2. 开启网络线程到发出一个完整的 http 请求(这一部分涉及到 dns 查询, TCP/IP 请求,五层因特网协议栈等知识)

  3. 从服务器接收到请求到对应后台接收到请求(这一部分可能涉及到负载均衡,安全拦截以及后台内部的处理等等)

  4. 后台和前台的 HTTP 交互(这一部分包括 HTTP 头部、响应码、报文结构、cookie 等知识点)

  5. 单独拎出来的缓存问题,HTTP 的缓存(这部分包括 HTTP 缓存头部, ETagcatch-control 等)

  6. 浏览器接收到 HTTP 数据包后的解析流程(解析 html:词法分析然后解析成 dom 树、解析 css 生成 css 规则树、合并成 render 树,然后 layoutpainting 渲染、 复合的合成、GPU 绘制、外链资源的处理、loadedDOMContentLoaded 等)

  7. CSS 的可视化格式模型(元素的渲染规则,如包含块、控制框、 BFCIFC 等概念)

  8. JS 引擎解析过程(JS 的解释阶段,预处理阶段,执行阶段生成执行上下文, VO,作用域链、回收机制等等)

  9. 其他(可以拓展不同的知识模块,如跨域、 web 安全、 hybrid 模式等等内容)

五、说一下 css3 的 animation

  • css3animationcss3 新增的动画属性,这个 css3 动画的每一帧是通过 @keyframes 来声明的, keyframes 声明了动画的名称,通过 fromto 或者是百分比来定义

  • 每一帧动画元素的状态,通过 animation-name 来引用这个动画,同时 css3 动画也可以定义动画运行的时长、动画开始时间、动画播放方向、动画循环次数、动画播放的方式

  • 这些相关的动画子属性有:animation-name 定义动画名、 animation-duration 定义动画播放的时长、 animation-delay 定义动画延迟播放时间、 animation-direction 定义动画的播放方向、 animation-iteration-count 定义播放次数、 animation-fill-mode 定义动画播放之处的状态、 animation-play-state 定义播放状态,如暂停运行等、animation-timeing-function 定义播放的方式,如恒速播放、艰涩播放等

六、谈⼀谈箭头函数与普通函数的区别?

  1. 函数体内的 this 对象,就是定义时所在的对象,⽽不是使⽤时所在的对象
  2. 不可以当作构造函数,也就是说,不可以使⽤ new 命令,否则会抛出⼀个错误
  3. 不可以使⽤ arguments 对象,该对象在函数体内不存在。如果要⽤,可以⽤ rest 参数 代替
  4. 不可以使⽤ yield 命令,因此箭头函数不能⽤作 generator 函数

七、BFC 是什么?触发 BFC 的条件是什么?有哪些应用场景?

  • 什么是 BFC

    MDN 对 BFC 的定义是:块格式化上下文是 web 页面的可视 css 渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。

  • 如何触发 BFC

    • 根元素
    • 浮动元素:float 除了 none 以外的属性值
    • 绝对定位元素(元素的 position 为 absolute 或 fixed)
    • display 为 inline-block, table-cells, flex, table
    • overflow 除了 visible 以外的属性值。
  • 应用场景

    • 避免外边距重叠
    • 防止浮动导致父元素高度塌陷
    • 清除内部浮动
    • 嵌套元素的 margin 重叠

八、DNS 解析的具体过程

  1. 检查浏览器缓存中是否缓存过该域名对应的 IP 地址
  2. 如果浏览器缓存中没有命中,将继续查找本机(操作系统)是否缓存过该 IP
  3. 向本地域名解析服务系统发起域名解析的请求(一般是本地运营商的机房)
  4. 向根域名解析服务器发起域名解析请求
  5. 根域名服务器返回 gTLD 域名解析服务器地址
  6. 向 gTLD 服务器发起解析请求
  7. gTLD 服务器接收请求并返回 Name Server 服务器(通常情况下就是你注册的域名服务器)
  8. Name Server 服务器返回 IP 地址给本地服务器
  9. 本地域名服务器缓存解析结果
  10. 返回解析结果给用户

九、React 中 setState 是同步的还是异步的

有时表现出同步,有时表现出异步

  1. setState 只在 React 自身的合成事件和钩子函数中是异步的,在原生事件和 setTimeout 中都是同步的。

  2. setState 的异步并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形成了所谓的异步,当然可以通过第二个参数 setState(partialState, callback) 中的 callback 拿到更新后的结果。

  3. setState 的批量更新优化也是建立在异步(合成事件、钩子函数)之上的,在原生事件和 setTimeout 中不会批量更新,在异步中如果对同一个值进行多次 setState, setState 的批量更新策略会对其进行覆盖,取最后一次的执行,如果是同时 setState 多个不同的值,在更新时会对其进行合并批量更新。

十、说一下 TCP 三次握手过程

  1. 客户端向服务端发送连接请求报文段。该报文段中包含自身的数据通讯初始序号。请求发送后,客户端进入 SYN-SENT 状态

  2. 服务端接收到客户端请求,发送应答,应答中也会包含自身的数据通讯初始序号,发送完成后便进入 SYN-RECEIVED 状态。

  3. 当客户端收到连接同意的应答后,还要向服务端发送一个确认报文。客户端发完这个报文段后便进入 ESTSBLISHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接建立成功。

十一、说一下 TCP 四次挥手过程

  1. 若客户端 A 认为数据发送完成,则它需要向服务端 B 发送连接释放请求。

  2. B 收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入 CLOSE_WAIT 状态,此时表明 A 到 B 的连接已经释放,不再接收 A 发的数据了。但是因为 TCP 连接时双向的,所以 B 仍旧可以发送数据给 A

  3. B 如果此时还有没发完的数据会继续发送,完毕后会向 A 发送连接释放请求,然后 B 便进入 LAST-ACK 状态。

  4. A 收到释放请求后,向 B 发送确认应答,此时 A 进入 TIME-WAIT 状态。该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃)时间,若该时间段内没有 B 的重发请求的话,就进入 CLOSED 状态。当 B 收到确认应答后,也便进入 CLOSED 状态。

十二、介绍一下对称加密和非对称加密

对称加密的过程:
  1. A 生成一份密钥,通过互联网发给 B
  2. A 生成明文,使用密钥加密,发送给 B
  3. B 使用密钥解密
对称加密优缺点

优点:算法公开、计算量小、加密速度快、加密效率高
缺点:在数据传送前,发送方和接收方必须商定好密钥,然后使双方都能保存好密钥。某次如果一方的密钥被泄露,那么加密信息也就不安全

非对称加密过程
  1. A 和 B 分别在本地生成一个公钥和一个私钥
  2. A 先拿到 B 的公钥
  3. A 使用 B 的公钥编码生成密文,传输给 B
  4. B 使用自己的私钥解锁
非对称加密优缺点

优点:安全性更高,公钥是公开的,秘钥是自己保存的,不需要将秘钥给别人
缺点:

  • 加密和解密花费时间长、速度慢,只适合对少量数据进行加密
  • 因为 B 的公钥是公开的,所以任何人都可用其公钥加密,伪装成 A 通信,解决办法是增加数字签名和证书

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

为了防止出现失效的连接请求报文段被服务端接收的情况,从而产生错误。

可以想象如下场景。客户端发送了一个连接请求 A ,但是因为网络原因造成了超时,这时 TCP 会启动超时重传的机制再次发送一个连接请求 B。此时请求顺利到达服务端,服务端应答完就建立了请求,然后接受数据后释放了连接。

假设这时连接请求 A 在两端关闭后终于抵达了服务端,那么此时服务端会认为客户端又需要建立 TCP 连接,从而应答了该请求并进入 ESTABLISHED 状态。但是客户端其实是 CLOSED 的状态,那么就会导致服务端一直等待,造成资源的浪费。

PS:在建立连接中,任意一段掉线,TCP 都会重发 SYN 包,一般会重试五次,在建立连接中可能会遇到 SYN Flood 攻击。遇到这种情况可以选择调低重试次数或者干脆在不能处理的情况下拒绝请求。

十四、https 的握手过程

  1. 客户端发出 https 请求,请求服务端建立 SSL 连接

  2. 服务端收到 https 请求,申请或自制数字证书,得到公钥和服务端私钥,并将公钥发送给客户端

  3. 客户端验证公钥,不通过验证则发出警告,通过验证则产生一个随机的客户端私钥

  4. 客户端将该随机生成的私钥与服务端公钥进行对称加密后传给服务端

  5. 服务端收到加密内容后,通过服务端私钥进行非对称解密,得到客户端私钥

  6. 服务端将客户端私钥和内容进行对称加密,并将加密内容发送给客户端

  7. 客户端收到加密内容后,通过客户端私钥进行对称解密,得到内容

十五、React 组件通信如何实现

React 组件通信方式:

  1. 父 -> 子:父组件可以向子组件通过传 props 的方式,向子组件进行通讯

  2. 子 -> 父:props + 回调,父组件向子组件传递 props 进行通讯,此 props 为作用域为父组件自身的函数,子组件调用该函数,将子组件想要传递的信息,作为参数,传递到父组件的作用域中

  3. 兄弟组件通信:找到这两个兄弟节点共同的父节点,结合上面两种方式由父节点转发信息进行通信

  4. 跨层级通信: Context 设计目的是为了共享那些对于一个组件树而言是全局的数据,对于跨越多层的全局数据通过 Context 通信再合适不过

  5. 发布订阅模式:我们可以通过引入 event 模块进行通信

  6. 全局状态管理工具:借助 Redux 或者 Mobx 等全局状态管理工具进行通信,这种工具会维护一个全局状态中心 Store,并根据不同的事件产生新的状态。

写在最后

前端的世界纷繁复杂,远非笔者所能勾画,部分面试题不是靠背诵记忆就能掌握的,希望我摘录的、总结的简单答案可以引起读者的兴趣,闲暇时可以自己深入总结,如果读者有更好的答案,或有想了解的题目,欢迎留言。

笔者新建了一个 github 仓库,对公众号内发布的面试题做进一步分类,同时也会在周六同步本周题目、公布下周问题,欢迎大家关注~

想要实时关注笔者最新的文章和最新的文档更新请关注公众号前端地基,后续的文章会优先在公众号更新.

github:关注笔者最新的仓库[1]

参考资料

[1]

关注笔者最新的仓库: https://github.com/lionel178/easy-web