2019 面试准备 - JS 防抖与节流 (超级 重要!!!!!)

Hello 小伙伴们,若是以为本文还不错,记得给个 star , 大家的 star 是我学习的动力!GitHub 地址html

 

本文涉及知识点前端

  • 防抖与节流
  • 重绘与回流
  • 浏览器解析 URL
  • DNS 域名解析
  • TCP 三次握手与四次挥手
  • 浏览器渲染页面

在本文中,jsliang 会讲解经过自我探索后关于上述知识点的我的理解,若有纰漏、疏忽或者误解,欢迎各位小伙伴留言指出。git

若是小伙伴对文章存有疑问,想快速获得回复。
或者小伙伴对 jsliang 我的的前端文档库感兴趣,也想将本身的前端知识整理出来。
欢迎加 QQ 群一块儿探讨:798961601github

一 目录

不折腾的前端,和咸鱼有什么区别web

目录
一 目录
二 前言
三 防抖与节流
3.1 防抖
3.2 节流
四 重绘与回流
五 浏览器解析 URL
六 DNS 域名解析
七 TCP 三次握手与四次挥手
八 浏览器渲染页面
九 总结
十 参考文献

二 前言

返回目录面试

在工做中,咱们可能碰到这样的问题:数据库

  • 用户在搜索的时候,在不停敲字,若是每敲一个字咱们就要调一次接口,接口调用太频繁,给卡住了。
  • 用户在阅读文章的时候,咱们须要监听用户滚动到了哪一个标题,可是每滚动一下就监听,那样会太过频繁从而占内存,若是再加上其余的业务代码,就卡住了。

因此,这时候,咱们就要用到 防抖与节流 了。后端

那么,讲到 防抖与节流,咱们能够顺带探秘下 重绘与回流浏览器

提及 重绘与回流,咱们就顺带把 浏览器输入 URL 后发生的事情 也关注一下,从而引出 DNSTCP 等知识点,最终串起来构成本文的轮廓,方便 jsliang 和小伙伴们对这块知识的整理与记忆。缓存

三 防抖与节流

返回目录

经过代码去了解某样事物,每每是了解某个知识点最快的形式。

3.1 防抖

返回目录

下面咱们有段防抖小案例代码。

若是小伙伴们手头有电脑,并感兴趣想先本身思考下什么是防抖。能够将代码复制到浏览器,尝试点击按钮,并关注下控制台,看看 Console 是如何打印的。

若是小伙伴们手头没有电脑,那么咱一块儿先瞅瞅代码实现,再看看下面 GIF 演示。(这样效果没有本身敲的直白有效)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>防抖</title>
</head>
<body>
  <button id="debounce">点我防抖!</button>

  <script>
    window.onload = function() {
      // 一、获取这个按钮,并绑定事件
      var myDebounce = document.getElementById("debounce");
      myDebounce.addEventListener("click", debounce(sayDebounce));
    }

    // 二、防抖功能函数,接受传参
    function debounce(fn) {
      // 四、建立一个标记用来存放定时器的返回值
      let timeout = null;
      return function() {
        // 五、每次当用户点击/输入的时候,把前一个定时器清除
        clearTimeout(timeout);
        // 六、而后建立一个新的 setTimeout,
        // 这样就能保证点击按钮后的 interval 间隔内
        // 若是用户还点击了的话,就不会执行 fn 函数
        timeout = setTimeout(() => {
          fn.call(this, arguments);
        }, 1000);
      };
    }

    // 三、须要进行防抖的事件处理
    function sayDebounce() {
      // ... 有些须要防抖的工做,在这里执行
      console.log("防抖成功!");
    }

  </script>
</body>
</html>

 

很好,相信小伙伴们已经看完了代码,下面咱们看看它的演示:

 

 

这时候,咱们能够抛出防抖的概念了:

  • 防抖任务频繁触发的状况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。

结合上面的代码,咱们能够了解到,在触发点击事件后,若是用户再次点击了,咱们会清空以前的定时器,从新生成一个定时器。意思就是:这件事儿须要等待,若是你反复催促,我就从新计时!

空讲无益,show you 场景:

  • 有个输入框,输入以后会调用接口,获取联想词。可是,由于频繁调用接口不太好,因此咱们在代码中使用防抖功能,只有在用户输入完毕的一段时间后,才会调用接口,出现联想词。

小伙伴们能够尝试看着上面的案例,先本身实现一遍这个场景的解决,若是感受不行,那就看:《防抖和节流的应用场景和实现》

知识点补充:何为 arguments
首先,后端转前端的同窗,能够将 arguments 理解为能实现重载函数功能的工具。
而后,咱们举个例子:在 function test() 这个方法中,因为咱们不肯定变量有多少,好比 test("jsliang", 24),又或者 test("LiangJunrong", "jsliang", "24"),这时候只须要在函数 test 中用 arguments 接收就好了。
最后,在 function test() { let arr1 = argument[0] } 中,arr1 就能够获取到传进来的第一个变量。
因此fn.call(this, arguments) 实际上是将不肯定变量替换到函数中了。

参考资料 1:《闲聊 JS 中的 apply 和 call》
参考资料 2:《js 中 arguments 的用法》

3.2 节流

返回目录

说完防抖,下面咱们讲讲节流,规矩就不说了,先上代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>节流</title>
</head>
<body>

  <button id="throttle">点我节流!</button>

  <script>
    window.onload = function() {
      // 一、获取按钮,绑定点击事件
      var myThrottle = document.getElementById("throttle");
      myThrottle.addEventListener("click", throttle(sayThrottle));
    }

    // 二、节流函数体
    function throttle(fn) {
      // 四、经过闭包保存一个标记
      let canRun = true;
      return function() {
        // 五、在函数开头判断标志是否为 true,不为 true 则中断函数
        if(!canRun) {
          return;
        }
        // 六、将 canRun 设置为 false,防止执行以前再被执行
        canRun = false;
        // 七、定时器
        setTimeout( () => {
          fn.call(this, arguments);
          // 八、执行完事件(好比调用完接口)以后,从新将这个标志设置为 true
          canRun = true;
        }, 1000);
      };
    }

    // 三、须要节流的事件
    function sayThrottle() {
      console.log("节流成功!");
    }

  </script>
</body>
</html>

 

很好,看完代码的小伙伴应该大体清楚是怎么回事了,下面咱们看 GIF 实现:

 

 

看完代码和 GIF 实现,咱们能够明白,节流便是:

  • 节流指定时间间隔内只会执行一次任务。

那么,节流在工做中的应用?

  1. 懒加载要监听计算滚动条的位置,使用节流按必定时间的频率获取。
  2. 用户点击提交按钮,假设咱们知道接口大体的返回时间的状况下,咱们使用节流,只容许必定时间内点击一次。

这样,在某些特定的工做场景,咱们就可使用防抖与节流来减小没必要要的损耗。

那么问题来了,假设面试官听到你这句话,是否是会接着问一句:“为何说上面的场景不节制会形成过多损耗呢?”

OK,这就涉及到浏览器渲染页面的机制了……

四 重绘与回流

返回目录

在说浏览器渲染页面以前,咱们须要先了解两个点,一个叫 浏览器解析 URL,另外一个就是本章节将涉及的 重绘与回流

  • 重绘(repaint):当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新,此时因为只须要 UI 层面的从新像素绘制,所以损耗较少

常见的重绘操做有:

  1. 改变元素颜色
  2. 改变元素背景色
  3. more ……
  • 回流(reflow):又叫重排(layout)。当元素的尺寸、结构或者触发某些属性时,浏览器会从新渲染页面,称为回流。此时,浏览器须要从新通过计算,计算后还须要从新页面布局,所以是较重的操做。

常见的回流操做有:

  1. 页面初次渲染
  2. 浏览器窗口大小改变
  3. 元素尺寸/位置/内容发生改变
  4. 元素字体大小变化
  5. 添加或者删除可见的 DOM 元素
  6. 激活 CSS 伪类(:hover……)
  7. more ……
  • 重点回流一定会触发重绘,重绘不必定会触发回流。重绘的开销较小,回流的代价较高。

看到这里,小伙伴们可能有点懵逼,你刚刚还跟我讲着 防抖与节流 ,怎么一会儿跳到 重绘与回流 了?

OK,卖个关子,先看下面场景:

  • 界面上有个 div 框,用户能够在 input 框中输入 div 框的一些信息,例如宽、高等,输入完毕当即改变属性。可是,由于改变以后还要随时存储到数据库中,因此须要调用接口。若是不加限制……

看到这里,小伙伴们能够将一些字眼结合起来了:为何须要 节流,由于有些事情会形成浏览器的 回流,而 回流 会使浏览器开销增大,因此咱们经过 节流 来防止这种增大浏览器开销的事情。

形象地用图来讲明:

 

 


 

这样,咱们就能够形象的将 防抖与节流重绘与回流 结合起来记忆起来。

那么,在工做中咱们要如何避免大量使用重绘与回流呢?:

  1. 避免频繁操做样式,可汇总后统一一次修改
  2. 尽可能使用 class 进行样式修改,而不是直接操做样式
  3. 减小 DOM 的操做,可以使用字符串一次性插入

OK,至此咱们就讲完两个部分了,那么问题又来了:“浏览器渲染过程当中,是否是也有重绘与回流?”“从浏览器输入 URL 到渲染成功的过程当中,究竟发生了什么?”

咱们,继续深刻探索……

五 浏览器解析 URL

返回目录

为了能让咱们的知识层面看起来更有深度,咱们应该考虑下面两个问题了:

  • 从浏览器输入 URL 到渲染成功的过程当中,究竟发生了什么?
  • 浏览器渲染过程当中,发生了什么,是否是也有重绘与回流?

OK,兴致来了,咱们就先从 浏览器解析 URL 看起,先来看看当用户输入 URL,到浏览器呈现给用户页面,经历了如下过程:

  • 版本 A
  1. 用户输入 URL 地址。
  2. 对 URL 地址进行 DNS 域名解析。
  3. 创建 TCP 链接(三次握手)。
  4. 浏览器发起 HTTP 请求报文。
  5. 服务器返回 HTTP 响应报文。
  6. 关闭 TCP 链接(四次挥手)。
  7. 浏览器解析文档资源并渲染页面。

讲到这里,忽然想起一个对话:

学生:“老师,这门课的考试重点是什么?”

老师:“全都是重点!”

enm...老师会不会被打我不知道,可是 jsliang 这样写会被怼我就清楚,因此,咱仍是结合上面的图,进一步勾勒咱们的结构:

 

 

很好,jsliang 感受本身的画图技术又进了一步~

①:虽然很感激网上有那么多的文章能够参考,可是在我查了二十来篇文章后,jsliang 以为这部分十有八九有问题撒,问了些小伙伴,它们有的说对,有的说错。不过,不妨碍小伙伴们继续往下看哈。
②:为了不出篓子,下面贴出另一个版本,小伙伴们能够在评论区说出你支持哪一个版本哈:

  • 版本 B
  1. 用户输入 URL 地址。
  2. 对 URL 地址进行 DNS 域名解析。
  3. 进行 TCP 链接。
  4. 进行 HTTP 报文的请求与响应。
  5. 浏览器解析文档资源并渲染页面。

在这里咱们能够清晰的了解到从 用户输入 URL,到浏览器呈现给用户页面,经历了哪些过程

那么剩下的就简单了:

  1. 什么是 DNS 解析,它是怎么个流程?
  2. 什么是 TCP 三次握手,什么是 TCP 四次挥手,它们的流程是怎样的?
  3. 浏览器解析文档资源并渲染页面是个怎样的流程?

Let's go~ 逐步完成下面三个知识点!

参考文献 1:《网页解析的全过程(输入url到展现页面)》
参考文献 2:《浏览器渲染页面过程剖析》

六 DNS 域名解析

返回目录

首先,咱们解决第一个问题:

  • 什么是 DNS 解析,它是怎么个流程?

DNS(Domain Name System)是 域名系统 的英文缩写,提供的服务是用于将主机名和域名转换为 IP 地址的工做:

域名:http://jsliang.top <---> DNS <---> IPV4:119.147.15.13

IPV4 是造假的,仅用来讲明 DNS 解析后能返回 IP 地址

因此,当用户在浏览器输入 http://jsliang.top 时,DNS 经历了如下步骤:

  1. 浏览器根据地址,在自身缓存中查找 DNS(域名服务器) 中的解析记录。若是存在,则直接返回 IP 地址;若是不存在,则查找操做系统中的 hosts 文件是否有该域名的 DNS 解析记录,若是有就返回。
  2. 在条件 1 中的浏览器缓存或者操做系统的 hosts 文件中都没有这个域名的 DNS 解析记录,或者已通过期,则向域名服务器发起请求解析这个域名。
  3. 先向本地域名服务器中请求,让它解析这个域名,若是解析不了,则向根域名服务器请求解析。
  4. 根服务器给本地域名服务器返回一个主域名服务器。
  5. 本地域名服务器向主域名服务器发起解析请求。
  6. 主域名服务器接收到解析请求后,查找并返回域名对应的域名服务器的地址。
  7. 域名服务器会查询存储的域名和 IP 的映射关系表,返回目标 IP 记录以及一个 TTL(Time To Live)值。
  8. 本地域名服务器接收到 IP 和 TTL 值,进行缓存,缓存的时间由 TTL 值控制。
  9. 将解析的结果返回给用户,用户根据 TTL 值缓存在本地系统缓存中,域名解析过程结束。

看文字老是难以理解的,跟着 jsliang 画张图过一遍,就感受清晰了:

 

 


 

七 TCP 三次握手与四次挥手

返回目录

而后,咱们解决第二个问题:

  • 什么是 TCP 三次握手,什么是 TCP 四次挥手,它们的流程是怎样的?

什么是 TCP 呢?TCP(Transmission Control Protocol 传输控制协议)是一种面向链接的、可靠的、基于字节流的传输层通讯协议。

简单来讲,它的做用就是将数据流从一台主机可靠地传输到另外一台主机。

至于具体的工做原理,这里暂时涉及不到,咱们目前只想知道两个点:三次握手与四次挥手

  • 三次握手
  1. 第一次握手:起初两端都处于 CLOSED 关闭状态,Client 将标志位 SYN 置为 1,随机产生一个值 seq = x,并将该数据包发送给 Server,Client 进入 SYN-SENT 状态,等待 Server 确认。
  2. 第二次握手:Server 收到数据包后由标志位 SYN = 1 得知 Client 请求创建链接,Server 将标志位 SYN 和 ACK 都置为 1,ack = x + 1,随机产生一个值 seq = y,并将该数据包发送给Client以确认链接请求,Server 进入 SYN-RCVD 状态,此时操做系统为该 TCP 链接分配 TCP 缓存和变量。
  3. 第三次握手:Client 收到确认后,检查 seq 是否为 x + 1,ACK 是否为 1,若是正确则将标志位 ACK 置为 1,ack = y + 1,而且此时操做系统为该 TCP 链接分配 TCP 缓存和变量,并将该数据包发送给 Server,Server 检查 ack 是否为 y + 1,ACK 是否为 1,若是正确则链接创建成功,Client 和 Server 进入 established 状态,完成三次握手,随后 Client 和 Server 就能够开始传输数据。

文字太乱,show you picture:

 

 


 

  • 四次挥手
  1. 第一次挥手:Client 的应用进程先向其 TCP 发出链接释放报文段(FIN = 1,序号 seq = u),并中止再发送数据,主动关闭 TCP 链接,进入 FIN-WAIT-1(终止等待1)状态,等待 Server 的确认。
  2. 第二次挥手:Server 收到链接释放报文段后即发出确认报文段,(ACK = 1,确认号 ack = u + 1,序号 seq = v),Server 进入 CLOSE-WAIT(关闭等待)状态,此时的 TCP 处于半关闭状态,Client 到 Server 的链接释放。

注:Client 收到 Server 的确认后,进入 FIN-WAIT-2(终止等待2)状态,等待 Server 发出的链接释放报文段。

  1. 第三次挥手:Server 已经没有要向 Client 发出的数据了,Server 发出链接释放报文段(FIN = 1ACK = 1,序号 seq = w,确认号 ack = u + 1),Server 进入 LAST-ACK(最后确认)状态,等待 Client 的确认。
  2. 第四次挥手:Client 收到 Server 的链接释放报文段后,对此发出确认报文段(ACK = 1seq = u + 1ack = w + 1),Client 进入 TIME-WAIT(时间等待)状态。此时 TCP 未释放掉,须要通过时间等待计时器设置的时间 2MSL 后,Client 才进入 CLOSED 状态。

文字太乱,show you picture:

 

 


 

OK,至此咱们就理解了 TCP 及其三次握手和四次挥手过程,为了方便小伙伴们形象记忆,jsliang 搞了个小故事,但愿小伙伴们能加深印象:

  • 三次握手 + 四次挥手形象记忆
  1. jsliang:(对妹子发起微信好友申请)“你好,我能够加你好友吗?” —— 第一次握手
  2. 妹子:(经过审核)“你好,很高兴认识你~” —— 第二次握手
  3. jsliang:“你好,我叫梁峻荣,前端折腾小能手……” —— 第三次握手
  4. ……(聊天内容)
  5. …………(聊天内容)
  6. ………………(聊天内容)
  7. …………(聊天内容)
  8. ……(聊天内容)
  9. jsliang:(感冒拍了张纸篓都是纸巾的图)“啊,好难受今天。” —— 第一次挥手
  10. 妹子:“卧槽,你好恶心!” —— 第二次挥手
  11. 妹子:“咱仍是当不认识吧,互删了,谢谢!” —— 第三次挥手
  12. jsliang:(呆)“不是,你听我说!” —— 第四次挥手
  13. 妹子:(果断删除好友) —— CLOSED
  14. jsliang:(!“我今天感冒了。” 妹子开启了好友验证,你还不是她好友。请先发送好友验证请求,对方验证经过后,才能聊天。) ——— CLOSED

OK,成功出糗,相信小伙伴们有了个很好的了解了。

那么,咱们继续前行探索。

参考文献 1:《TCP三次握手和四次挥手过程》
参考文献 2:《TCP的三次握手与四次挥手(详解+动图)》

八 浏览器渲染页面

返回目录

最后,咱们解决第三个问题:

  • 浏览器解析文档资源并渲染页面是个怎样的流程?

话很少说,一块儿来看:

  1. 浏览器经过 HTMLParser 根据深度遍历的原则把 HTML 解析成 DOM Tree。
  2. 浏览器经过 CSSParser 将 CSS 解析成 CSS Rule Tree(CSSOM Tree)。
  3. 浏览器将 JavaScript 经过 DOM API 或者 CSSOM API 将 JS 代码解析并应用到布局中,按要求呈现响应的结果。
  4. 根据 DOM 树和 CSSOM 树来构造 render Tree。
  5. layout:重排(也能够叫回流),当 render tree 中任一节点的几何尺寸发生改变,render tree 就会从新布局,从新来计算全部节点在屏幕的位置。
  6. repaint:重绘,当 render tree 中任一元素样式属性(几何尺寸没改变)发生改变时,render tree 都会从新画,好比字体颜色,背景等变化。
  7. paint:遍历 render tree,并调动硬件图形 API 来绘制每一个节点。

文字讲解确定仍是不够清晰的,可是 jsliang 画了几张图也累了,因此我们 来了一张图:

 

 


 

这样,咱们就对 浏览器渲染页面过程 一清二楚啦~

参考文献:《一篇文章搞定前端面试》

九 总结

返回目录

至此,咱们回顾下本身作了什么?

  1. 咱们在工做中碰到一些问题,这些问题会卡住页面,因而咱们查资料,知道想要减小浏览器的开销,咱们就须要使用 防抖与节流
  2. 使用 防抖与节流 解决完问题后,咱们好奇为何会有这样的操做,因而咱们深刻了解了下 重绘与回流
  3. 重绘与回流 只告诉了咱们浏览器在 CSS 上的渲染,咱们须要进一步了解 浏览器渲染页面 的详细过程,但洋葱仍是要一层一层剥开的,因此咱们须要从 浏览器解析 URL 开始了解。
  4. 浏览器解析 URL 中,咱们顺带了解下 DNS 域名解析TCP 三次握手与四次挥手 这两个知识点。
  5. 最后,咱们终于知道了 浏览器渲染页面 是怎么一回事。

综上,若是咱们仅仅是须要关注面试的一个点,咱们极可能由于不知头尾,而被面试官问得哑口无言。

可是,若是咱们知道一个知识点,并对其进行思路发散,深刻学习,相信面试官问起来的时候,小伙伴们就能够侃侃而谈,而不会被问地体无完肤了!

最后祝小伙伴们找到合适的满意的工做~

十 参考文献

返回目录

  1. 《函数防抖和节流》
  2. 《节流 & 防抖》
  3. 《JS奇淫巧技:防抖函数与节流函数》
  4. 《闲聊 JS 中的 apply 和 call》
  5. 《js 中 arguments 的用法》
  6. 《防抖和节流的应用场景和实现》
  7. 《网页解析的全过程(输入url到展现页面)》
  8. 《浏览器渲染页面过程剖析》
  9. 《一篇文章搞定前端面试》

做者:jsliang连接:https://juejin.im/post/5c87b54ce51d455f7943dddb来源:掘金著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。

相关文章
相关标签/搜索