防抖和节流
防抖和节流属于开发中常用的两种前端性能优化的技术。其目的是为了防止用户高频的操作某一功能,从而导致频繁发送请求或者造成浏览器的性能下降。
防抖
防抖(Debouncing)的核心原理是在事件发生时设置一个定时器,在指定时间后再执行操作。如果在该时间之前相同事件被触发,则清除之前的定时器并重新设置一个新的定时器,直到指定时间间隔内没有新的事件触发,才会执行最终的操作。这样可以确保操作仅在事件信号稳定后执行一次,从而避免了频繁执行的问题。
举个例子,当我们在搜索框中输入关键词时,输入框会不断触发oninput事件,如果每次输入都需要请求服务器,会造成不必要的请求浪费。此时使用防抖的话,可以实现设置一个规定的时间,在这规定时间内的事件触发不发送请求,只在规定时间结束后请求一次服务器数据,减少了请求次数和服务器的负载。
/**
* 防抖
* debounce函数接受func和delay两个参数,其中func是要延迟执行的函数,delay是指定的延迟时间。每当func函数被调用时,它将清除先前设置的定时器,并创建一个新的定时器等待执行。在指定的延迟时间之后,func函数将被执行,传递先前接收到的参数和上下文。
*/
let debounce = (func, delay) => {
let timer = null; //定时器变量
return function (...args) {
//...args rest参数 ES6中引入rest参数(形式为'...变量名'),用于获取函数的多余参数。rest参数之后不能再有其他参数(即只能是最后一个参数)。
// 对timer进行了闭包,所以timer占据的内存一直存在。timer作为定时器的返回值,里面的数据是一个正整数,表示排队的队列号,默认从1开始,依次递增。
// clearTimeout(timer)只是让当前这个队列失效,并非清空timer的值,timer中的值还存在。
clearTimeout(timer);
// timer = null 清空当前timer中的值。这个可有可无,这里简单记录一下。
timer = null;
timer = setTimeout(() => {
// apply更改this指向
func.apply(this, args);
}, delay);
};
};
节流
节流(Throttling)的核心思想是在指定间隔内只调用一次函数,而忽略其他请求。通过这种方式,可以确保函数仅在特定时间间隔内被调用,从而减少函数的执行次数,并提高应用程序的性能和响应能力。
举个例子,当我们拖动网页上的滚动条时,会不断触发onscroll事件,如果每次触发都去计算滚动距离,会造成浏览器的性能下降。此时使用节流的话,可以实现将一定时间内的多次触发限制为一次操作,只计算一次滚动距离,稀释次数,从而提高用户体验。
/**
1. 节流
2. throttle函数接受func和delay两个参数,其中func是要限制频率的函数,delay是指定的时间间隔。每当func函数再次被调用时,如果上一个调用距离现在已经超过了指定间隔,则再次执行func, 否则无视该次调用并返回。
*/
let throttle = (func, delay) => {
let timer = null; //定时器变量
return function (...args) {
// 判断当前是否设置定时器
if (!timer) {
timer = setTimeout(() => {
func.apply(this, args);
// 清除定时器
timer = null;
}, delay);
}
};
};
export { debounce, throttle };
闭包
因为防抖和节流都是基于闭包实现的,这里再简单介绍下闭包。
闭包:可以理解为函数嵌套函数,内部函数可以引用外部函数的参数和变量。参数和变量不会被垃圾回收机制回收。
相比较全局变量和局部变量,闭包有两大特点:
1.闭包拥有全局变量的不被释放的特点
2.闭包拥有局部变量的无法被外部访问的特点
闭包的好处:
1.可以让一个变量长期在内存中不被释放
2.避免全局变量的污染,和全局变量不同,闭包中的变量无法被外部使用
3.私有成员的存在,无法被外部调用,只能直接内部调用
摘自https://blog.youkuaiyun.com/happy_kx/article/details/124330489
HTML案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>防抖和节流</title>
</head>
<body>
<div>
防抖:<input id="search" type="text">
</div>
<script type="module">
// 本地HTML页面使用ES6语法,需要在script中配置type="module" 并在vsCode中安装并启动live Server扩展,重启之后右键点击open with live server
import { debounce, throttle } from "./util/debounceOrThrottle.js"
// 防抖案例
let inputDom = document.querySelector('#search');
let debounceFunc = debounce(getData, 1000);
inputDom.addEventListener('input', function () {
debounceFunc('防抖')
});
// 获取数据
function getData(val) {
console.log('获取数据' + val)
};
// 节流案例
let throttleFunc = throttle(getData, 1000);
document.addEventListener('click', function () {
// 传递参数
throttleFunc('节流')
})
</script>
</body>
</html>
本地HTML页面使用es6语法参考https://blog.youkuaiyun.com/cc18868876837/article/details/113915176
这里简单记录下防抖和节流。