前置
大家好,我又来了,今天我们说一下,JavaScript中的防抖和节流,防抖和节流是前端最基础的优化
,在面试中,面试官也是经常问到的,我们马上开始
开始
什么是防抖? 防抖:是一个频发的函数,在规定的时间内,只能让函数只能执行一次
防抖的应用场景有哪些呀?
- 用户输入搜索框的时候,为了避免多次敲击键盘,而每次都会发生
获取数据
如下代码:
function depagect(func,times){
//定义一个标识符
var timer
return function(){
//清空定时器
clearTimeout(timer)
//获取原生event参数
var event=arguments[0]
//创建定时器
timer = setTimeout(function(){
func(event)
},times)
}
}
$('.input').on('keyup', debounce(handle, 1000))
- 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位
- 文本编辑器实时保存,当无任何更改操作一秒后进行保存
防抖的类型分为?
- 立即执行版本 立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。 代码如下:
/**
* @description:
* @param {*} func 触发的事件
* @param {*} wait 多少时长才执行事件
* @return {*}
*/
function debounce(func,times){
//定义一个标识符
let timeout
//返回一个函数
return function(){
//定义当前的this
const ontext = this
//获取原生event参数
const args = [...arguments]
//判断如果是timeout,就清除定时器
if(timeout) clearTimeout(timeout);
//取反
const callNow=!timeout
timeout=setTimeout(()=>{
timeout=null
},times)
//如果是callNow,就把func应用到context,并追加args
if(callNow) func.apply(context,args)
}
}
$('.input').on('keyup', debounce(handle, 1000))
- 非立即执行版本 非立即执行版的意思是触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
代码如下
function debounce(func, wait) {
let timeout;
return function(){
// 获取当前作用域和参数
const context = this;
const args = [...arguments]
// 如果当前timeout 存在
// 清空定时器,再次等待wait时间过后再次执行事件
if(timeout) clearTimeout(timeout)
// 定时执行 传递进来的事件
timeout = setTimeout(()=>{
func.apply(context,args)
},wait)
}
}
$('.input').on('keyup', debounce(handle, 1000))
-
合成版本 通过传递
Boolean
来决定执行哪种版本。 -
true
为立即执行版 -
false
为非立即执行版本
debounce(func,1000,true)
代码如下
/**
* @desc 函数防抖
* @param func 函数
* @param wait 延迟执行毫秒数
* @param immediate true 表立即执行,false 表非立即执行
*/
function debounce(func, wait, immediate) {
let timeout;
return function () {
const context = this;
const args = [...arguments];
if (timeout) clearTimeout(timeout);
if (immediate) {
const callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
else {
timeout = setTimeout(() => {
func.apply(context, args)
}, wait);
}
}
}
节流
什么是节流?
所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。 节流会稀释函数的执行频率。
节流应用场景有哪些?
scroll
事件,每隔一秒计算一次位置信息等- 浏览器播放事件,每个一秒计算一次进度信息等
input
输入框在搜索内容时,可以控制多少s 在执行请求,避免多次发起请求,节约性能。
节流有两种实现
- 时间戳版本
function throttle(func, wait) {
var previous = 0;
return function() {
let now = Date.now();
let context = this;
let args = arguments;
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
}
}
- 定时器版本
function throttle(func, wait) {
let timeout;
return function() {
let context = this;
let args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
代码解析
当执行 throttle
函数时,timeout
默认为 undefined
, 此时, ! timeout
为 true
时,执行 定时器,并且 将 timeout
为 null,即为 false
, 再次执行 throttle
函数时, !timeout
又为 true
,再次执行定时器。
通过 timeout
的状态来达到节流的控制
总结
-
防抖: 触发事件后,一定时间后再执行事件,可以
立即执行
也可以一定时间再执行
-
节流: 控制流量,在单位时间内只能请求一次,避免多次触发事件,影响服务器性能。