彻底搞懂JavaScript防抖与节流

今天为大家带来一篇JS重难点的知识体系,这也是前端高薪必备的重难点知识,而且防抖与节流在各大企业前端面试过程中经常会考到的高频面试题!

 

为了更好的帮助大家理解防抖与节流,我们特意从我们的系统班(星辰班)中节选了两节课详细的讲解!放在钉钉群直播回放里面,大家可以看完这个文章之后,可以通过最底部的微信二维码添加助理老师,加入三十天计划群里学习!(如果你已经添加了助理老师,那还等什么,赶紧去问问老师,加入交流群学习吧!)

有同学反馈:

看了那么多面试题和答案,还不如老师一节课讲的通透,听了不过瘾还想继续听 ^_^

 

一、为什么需要防抖与节流

我们要了解什么是防抖与节流?这就需要回归到现实的应用场景来谈。

如果我们要监听浏览器滚动事件,或监听输入框值变化查询搜索结果等等,这些场景有个共同特点,频繁执行,然而我们不需要太频繁执行,比如滚动事件,间隔几百毫秒或者一秒执行回调就能满足业务需求,所以才有了节流和防抖的概念,目的是减少事件回调执行,提高浏览器性能。

接下来我们通过一个常见的防抖案例:搜索查询来展开讲解,帮助大家理解防抖。然后我们再通过一个常见的节流案例:滚动加载更多来展开讲解,帮助大家理解节流。

二、防抖案例:搜索查询

比如我们在一个表单中输入内容,JS通过监听输入框值的变化来查询搜索结果,我们会通过keyup事件来处理,当键盘弹起时就会触发keyup事件,在事件处理函数中发送请求处理查询结果。在我们输入内容时,会频繁的触发keyup事件,然而我们并不希望太频繁触发keyup事件处理函数发送请求查询。我们希望当我们擡起键盘间隔几百毫秒后再触发keyup事件处理函数发送请求查询(如果在间隔时间内再次触发keyup事件,就会把上一次的定时器清除,重新再计时)。因为频繁的触发增加了浏览器的性能消耗,同时也增加了对服务器的请求次数,增加服务器的压力。具体代码实现如下:

当我们以正常的速度在输入框中输入内容时,两种效果的前后对比

未添加防抖前的效效果

<body>
搜索查询:<input type="text" id="search" />
<script>
const search = document.getElementById("search");
var i = 0;
search.onkeyup = function () {
//处理查询内容....
console.log(i++);//每触发一次,i+1
};
</script>
</body>

 

 

 

添加防抖前的效效果

添加防抖代码后的效果<body>
搜索查询:<input type="text" id="search" />
<script>
const search = document.getElementById("search");
var i = 0;
var timer = null;
search.onkeyup = function () {
//如果之前的定时器还在,则清除
if (timer) {
clearTimeout(timer);
}
//在400毫秒后再触发
timer = setTimeout(function () {
//处理查询内容...
console.log(i++);
timer = null; //本次查询完成,则定时器清除,以方便下次查询处理
}, 400);
};
</script>
</body>

 

>每次键盘擡起都会触发keyup事件,但是keyup事件需要在400ms后才会处理查询操作,所以在下次触发keyup时,时间在400ms内,就会把上一次的定时器给清除了,本质上就没有触发查询操作。所以在所有电话号码输入完成后,400ms后就触发了一次查询操作。这样做的好处减少事件回调执行,提高浏览器性能。

 

三、什么是防抖及应用场景

防抖的概念

 

在连续的事件中,只需触发最后一次回调,也就是将几次操作合并为一此操作进行。原理是维护一个计时器,规定在delay(延迟)时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。

 

应用场景

 

搜索框输入查询、手机号、邮箱验证输入检测。只需用户最后一次输入完,再发送请求

窗口大小resize。只需窗口调整完成后,计算窗口大小,防止重复渲染。

四、防抖函数的封装

<script>
   //fn为事件处理函数   delay延迟时间
   function debounce(fn, delay) {
       var timer = null;
       return function () {
           if (timer) {
               clearTimeout(timer);
          }
           timer = setTimeout(() => {
               fn.apply(this, arguments); //this和参数
               timer = null;
          }, delay);
      };
  }
</script>

五、节流案例:滚动加载更多

接下来我们通过滚动加载更多为案例来展开讲解,帮助大家理解节流。

当我们滚动浏览器的滚动条时,会频繁触发scroll事件。我们通过监听浏览器scroll事件来断判断滚动条位置,如果滚动条滚动到页面的最底部,则就会加载更多信息。因为滚动时会频繁触发scroll事件,就会造成频繁的判断滚动条位置。

而我们并不希望每次触发scroll事件都需要去判断滚动条的位置,来决定是否加载更多,我们希望能间隔一定时间(几百毫秒)再判断一次,然后决定是否加载更多。如果时间不够,啥处理也不做,这样就能减少浏览器性能的消耗。

滚动加载更多源理:

  • 可视区的高度 + 滚动条滚动高度 >=文档高度 (整个滚动高度) 时就触发加载更多信息

未添加节流处理前的效果

scroll事件函数中的代码,在scroll事件触发时会频繁的被执行,特别消耗性能

<script>
var i = 0;
window.onscroll = function () {
//会频繁的处理以下代码,特别消耗性能
console.log(++i);//测试被执行的次数
var scrollTop = document
.documentElement.scrollTop;
var clientHeight = document
.documentElement.clientHeight;
var scrollHeight = document
.documentElement.scrollHeight;
if (scrollTop + clientHeight + 10 >= scrollHeight) {
//满足以上条件,则加载更多数据
console.log("开始加载更多数据....");
}
};
</script>

 

 

添加节流处理后的效果

 

scroll事件中的代码,会在事件触发时,每隔100ms触发一次。

<script>
var i = 0;
var timer = null;
window.onscroll = function () {
if (timer) {
return;
}
timer = setTimeout(function () {
console.log(++i);//测试被执行的次数
var scrollTop = document
.documentElement.scrollTop;
var clientHeight = document
.documentElement.clientHeight;
var scrollHeight = document
.documentElement.scrollHeight;
if (scrollTop + clientHeight + 10 >= scrollHeight) {
//满足以上条件,则加载更多数据
console.log("开始加载更多数据....");
}
timer = null;
}, 100);
};
</script>

同样的布局,同样的效果,在未做节流处理和做了节流处理,两者效果上有很大的差异。从头部滚动到底部触发加载更多,未做节流处理,共触发了35次代码的执行,而做了节流处理的,只触发了6次代码的执行。

 

 

六、什么是节流及应用场景

什么是节流

使得一定时间内只触发一次函数。原理是通过判断是否到达一定时间来触发函数。

节流应用场景

监听滚动事件判断是否到页面底部自动加载更多

搜索联想功能

DOM元素的拖拽功能实现

射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)

防止高频点击提交,防止表单重复提交;

 

七、节流函数的封装

<script>
   function throttle(fn, delay) {
       var timer = null;
       return function () {
           if (timer) {
               return;
          }
           timer = setTimeout(() => {
               fn.apply(this, arguments);//把this和参数传递过去
               timer = null;
          }, delay);
      };
  }
</script>

八、总结防抖与节流

不同点

 

节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数

防抖只是在最后一次事件后才触发一次函数。

应用场景

 

防抖应用场景

搜索框输入查询、手机号、邮箱验证输入检测。只需用户最后一次输入完,再发送请求

窗口大小resize。只需窗口调整完成后,计算窗口大小,防止重复渲染。

节流应用场景

监听滚动事件判断是否到页面底部自动加载更多

搜索联想功能

DOM元素的拖拽功能实现

射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)

防止高频点击提交,防止表单重复提交;

 

相同点

 

都可以通过使用 setTimeout 实现

降低回调执行频率。节省计算资源


防抖节流是JS阶段重要的教学内容,如果你正在学习JS或者已经在我们的三十天计划中完成了4个综合项目实战,那不妨可以听下这个课程体系,三十天计划群里还提供了算法、数组等知识体系!

 

 

 

更多完整JavaScript课程体系在我们的系统班里有完整的呈现,包含了JavaScript基础篇、重点、算法、原理、面试题、实战案例讲解!同时也为你提供了前端高级工程师成长体系!(详细看下图内容)

 

如果需要深度学习的同学可以点击下方链接了解详细的课程以及课程的报名方式!(,可以先领取以上推荐的几节JS课程学习,再来参与系统学习,不定期会推出活动,有大额优惠券推出,活动详情联系助理老师了解即可!)

Web 前端高级工程师系统课 | arry老师的博客-艾编程

如果你才开始学习前端,那么可以先学习我们的三十天计划(零基础的同学报名系统班同学可以和老师沟通制定学习计划,可以得到更快的成长!)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章