函数防抖和函数节流
优化高频率执行js代码的一种手段,js中的一些事件如浏览器的resize、scroll,鼠标的mousemove、mouseover,input输入框的keypress等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能。为了优化体验,需要对这类事件进行调用次数的限制。
相关例子代码如下:
html一样比较简单:
防抖
在事件被触发delay秒后再执行回调,如果在这n秒内又被触发,则重新计时。--->直白:比如click事件,在规定时间内只能执行一次,若多次点击,只执行最后一次;
var input = document.getElementsByTagName('input')[0]; input.onchange = debounce(function(e) { console.log(e.value) }, 2000) //防抖debounce function debounce(fn, delay) { var timer = null; return function() { // var _this = this, // _arguments = this.args; clearTimeout(timer) timer = setTimeout(() => { fn(this) }, delay) } }
以上代码就是函数防抖,如果直接执行input的onchange事件只要点击回车,就会输出;使用debounce降低了降低回调执行频率。节省计算资源。这样在2000内执行一次,若重复点击,这重新计算;
注意问题:
①timer的作用域,这里使用回调是为了强调timer的作用域;
②this的指向问题,定时器中this的指向是window,所有可以使用箭头函数或者fn.apply(_this,_args)来处理;
节流
每隔一段时间,只执行一次函数。---》直白:比如click事件,在规定时间内,就执行一次,其他的点击都是无效的。
解决方法一:定时器节流。
①:利用一个开关switchT控制点击事件,在用一次性定时器在delay内再恢复
var input = document.getElementsByTagName('input')[0]; input.onchange = throttles(function(e) { console.log(e.value) }, 2000) // 节流throttles function throttles(fn, delay) { var switchT = false; return function() { if (switchT) return; switchT = true; setTimeout(() => { switchT = false; }, delay) fn(this) } }
②:通过时间戳延时
// 节流throttles function throttles(fn, delay) { var timer = null; return function() { if (timer) return; timer = setTimeout(() => { fn(this) timer = null; }, delay) } }
解决方法二:时间戳节流。使用时间来控制,当前时间与之前的时间间隔超过了delay,就可以再次执行
var input = document.getElementsByTagName('input')[0]; input.onchange = throttles(function(e) { console.log(e.value) }, 2000) // 节流throttles function throttles(fn, delay) { var previous = 0; return function() { var current = new Date(); if (current - previous < delay) return; fn(this) previous = current; } }
常见应用场景
函数防抖的应用场景
连续的事件,只需触发一次回调的场景有:
- 搜索框搜索输入。只需用户最后一次输入完,再发送请求
- 手机号、邮箱验证输入检测
- 窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
函数节流的应用场景
间隔一段时间执行一次回调的场景有:
- 滚动加载,加载更多或滚到底部监听
- 谷歌搜索框,搜索联想功能
- 高频点击提交,表单重复提交
参考文章:
此文章是自己的一个笔记总结,如若有不对的地方或者需要补充的地方,还望提出,谢谢!