详解JS函数防抖


Posted in Javascript onJune 05, 2020

一、什么是函数防抖

       概念:函数防抖(debounce),就是指触发事件后,在 n 秒内函数只能执行一次,如果触发事件后在 n 秒内又触发了事件,则会重新计算函数延执行时间。

       举个栗子,坐电梯的时候,如果电梯检测到有人进来(触发事件),就会多等待 10 秒,此时如果又有人进来(10秒之内重复触发事件),那么电梯就会再多等待 10 秒。在上述例子中,电梯在检测到有人进入 10 秒钟之后,才会关闭电梯门开始运行,因此,“函数防抖”的关键在于,在 一个事件 发生 一定时间 之后,才执行 特定动作

二、为什么需要函数防抖

前端开发过程中,有一些事件,常见的例如,onresize,scroll,mousemove ,mousehover 等,会被频繁触发(短时间内多次触发),不做限制的话,有可能一秒之内执行几十次、几百次,如果在这些函数内部执行了其他函数,尤其是执行了操作 DOM 的函数(浏览器操作 DOM 是很耗费性能的),那不仅会浪费计算机资源,还会降低程序运行速度,甚至造成浏览器卡死、崩溃。这种问题显然是致命的。

       除此之外,短时间内重复的 ajax 调用不仅会造成数据关系的混乱,还会造成网络拥塞,增加服务器压力,显然这个问题也是需要解决的。

三、函数防抖如何解决上述问题

       根据上面对问题的分析,细细思索,可以想到如下解决方案。

       函数防抖的要点,是需要一个 setTimeout 来辅助实现,延迟运行需要执行的代码。如果方法多次触发,则把上次记录的延迟执行代码用 clearTimeout 清掉,重新开始计时。若计时期间事件没有被重新触发,等延迟时间计时完毕,则执行目标代码。

四、函数防抖的代码实现

       根据以上分析,我们对 “函数防抖” 来进行简单的代码实现,如下:

function debounce(fn,wait){
 var timer = null;
 return function(){
  if(timer !== null){
   clearTimeout(timer);
  }
  timer = setTimeout(fn,wait);
 }
}
 
function handle(){
 console.log(Math.random());
}
 
window.addEventListener("resize",debounce(handle,1000));

五、函数节流的使用场景

       函数防抖一般用在什么情况之下呢?一般用在,连续的事件只需触发一次回调的场合。具体有:

       搜索框搜索输入。只需用户最后一次输入完,再发送请求;

       用户名、手机号、邮箱输入验证;

       浏览器窗口大小改变后,只需窗口调整完后,再执行 resize 事件中的代码,防止重复渲染。

       目前遇到过的用处就是这些,理解了原理与实现思路,小伙伴可以把它运用在任何需要的场合,提高代码质量。

总结

       函数防抖其实是分为 “立即执行版” 和 “非立即执行版” 的,根据字面意思就可以发现他们的差别,所谓立即执行版就是 触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。 而 “非立即执行版” 指的是 触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。。

       在开发过程中,我们需要根据不同的场景来决定我们需要使用哪一个版本的防抖函数,一般来讲上述的防抖函数都能满足大部分的场景需求。但我们也可以将非立即执行版和立即执行版的防抖函数结合起来,实现最终的双剑合璧版本的防抖函数,以下为小伙伴们做了简单的实现:

/**
* @desc 函数防抖---“立即执行版本” 和 “非立即执行版本” 的组合版本
* @param func 需要执行的函数
* @param wait 延迟执行时间(毫秒)
* @param immediate---true 表立即执行,false 表非立即执行
**/
function debounce(func,wait,immediate) {
let timer;

return function () {
let context = this;
let args = arguments;

if (timer) clearTimeout(timer);
if (immediate) {
var callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait)
if (callNow) func.apply(context, args)
} else {
timer = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}
}

function handle(){
console.log(Math.random());
}

// window.addEventListener("mousemove",debounce(handle,1000,true)); // 调用立即执行版本
window.addEventListener("mousemove",debounce(handle,1000,false)); // 调用非立即执行版本

以上就是详解JS函数防抖的详细内容,更多关于JS函数防抖的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
URL编码转换,escape() encodeURI() encodeURIComponent()
Dec 27 Javascript
JS正则表达式验证数字代码
Jan 28 Javascript
javascript创建createXmlHttpRequest对象示例代码
Feb 10 Javascript
按Enter键触发事件的jquery方法实现代码
Feb 17 Javascript
深入剖析JavaScript编程中的对象概念
Oct 21 Javascript
AngularJs学习第八篇 过滤器filter创建
Jun 08 Javascript
基于Vuejs框架实现翻页组件
Jun 29 Javascript
jquery实现焦点轮播效果
Feb 23 Javascript
Angular4.0中引入laydate.js日期插件的方法教程
Dec 25 Javascript
JQuery扩展对象方法操作示例
Aug 21 jQuery
解决Vue+Electron下Vuex的Dispatch没有效果问题
May 20 Javascript
微信小程序实现注册登录功能(表单校验、错误提示)
Dec 10 Javascript
Vuex的各个模块封装的实现
Jun 05 #Javascript
js实现表单项的全选、反选及删除操作示例
Jun 05 #Javascript
一篇文章带你使用Typescript封装一个Vue组件(简单易懂)
Jun 05 #Javascript
vscode 插件开发 + vue的操作方法
Jun 05 #Javascript
vue渲染方式render和template的区别
Jun 05 #Javascript
Vue是怎么渲染template内的标签内容的
Jun 05 #Javascript
Vue 如何使用props、emit实现自定义双向绑定的实现
Jun 05 #Javascript
You might like
PHP 文本文章分页代码 按标记或长度(不涉及数据库)
2012/06/07 PHP
Laravel框架自定义公共函数的引入操作示例
2019/04/16 PHP
php日志函数error_log用法实例分析
2019/09/23 PHP
javaScript parseInt字符转化为数字函数使用小结
2009/11/05 Javascript
深入理解JavaScript系列(16) 闭包(Closures)
2012/04/12 Javascript
jQuery遍历json的方法(推荐)
2016/06/12 Javascript
BootStrap 轮播插件(carousel)支持左右手势滑动的方法(三种)
2016/07/07 Javascript
jQuery实现鼠标悬停3d菜单展开动画效果
2017/01/19 Javascript
BootStrap+Mybatis框架下实现表单提交数据重复验证
2017/03/23 Javascript
详解vue渲染从后台获取的json数据
2017/07/06 Javascript
Vue组件开发之LeanCloud带图形校验码的短信发送功能
2017/11/07 Javascript
谈谈JS中的!!
2017/12/07 Javascript
vue与vue-i18n结合实现后台数据的多语言切换方法
2018/03/08 Javascript
小程序云开发初探(小结)
2018/10/24 Javascript
[44:15]DOTA2上海特级锦标赛主赛事日 - 5 败者组决赛Liquid VS EG第二局
2016/03/06 DOTA
[40:01]OG vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
Python基于checksum计算文件是否相同的方法
2015/07/09 Python
python dict.get()和dict['key']的区别详解
2016/06/30 Python
Apache如何部署django项目
2017/05/21 Python
安装python时MySQLdb报错的问题描述及解决方法
2018/03/20 Python
对numpy的array和python中自带的list之间相互转化详解
2018/04/13 Python
Python中文件的读取和写入操作
2018/04/27 Python
Python 实现数据结构中的的栈队列
2019/05/16 Python
python yield和Generator函数用法详解
2020/02/10 Python
python用pip install时安装失败的一系列问题及解决方法
2020/02/24 Python
Python类及获取对象属性方法解析
2020/06/15 Python
html5在移动端的屏幕适应问题示例探讨
2014/06/15 HTML / CSS
Mio Skincare中文官网:肌肤和身体护理
2016/10/26 全球购物
智能电子秤、手表和健康监测仪:Withings(之前为诺基亚健康)
2018/10/30 全球购物
波兰汽车配件网上商店:iParts.pl
2020/09/08 全球购物
说出你对remoting 和webservice的理解和应用
2014/06/08 面试题
优秀求职信范文分享
2013/12/19 职场文书
2014年幼儿园元旦活动方案
2014/02/13 职场文书
导游词之张家界
2019/10/31 职场文书
七年级作文之雪景
2019/11/18 职场文书
Python机器学习应用之工业蒸汽数据分析篇详解
2022/01/18 Python