layout: post
title: 防抖节流的实现和使用
subtitle:
date: 2023-10-15
author: BY
catalog: true
tags:
- 前端
- Javascrit
防抖和节流是前端优化的一种常用方法。防抖,n秒后再执行该事件+n秒内若重新触发改事件,则重新计时。换句话说,如连续点击按钮,则按钮上绑定的事件永远不会实现。节流,n秒内不管点击多少次都只执行一次。lodash提供了debounce和throttle,这两个函数应该叫做“防抖化”和“节流化”函数,传入一个函数,使其具备防抖和节流的特性,简单实现一个防抖节流函数。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button onclick="testDebounce()">测试防抖节流</button>
<script>
testDebounce = Debounce(() => {
console.log('测试防抖节流')
}, 3000)
function Debounce(fn, interval = 1000) {
let timer
return function() {
clearTimeout(timer)
timer = setTimeout(() => fn(), interval)
}
}
</script>
</body>
</html>
以上就简单实现了一个不带参数的防抖函数,这时候返回的函数是没有执行参数的,优化一波。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button onclick="testDebounce('arg')">测试防抖</button>
<script>
testDebounce = Debounce((arg) => {
console.log(arg)
}, 500)
function Debounce(fn, interval = 1000) {
let timer
return function() {
let context = this, args = arguments
clearTimeout(timer)
timer = setTimeout(() => fn.call(context, ...args), interval)
}
}
</script>
</body>
</html>
接下来实现一个节流函数,节流函数的效果是,不管点击多少次,只执行第一次,之后的若干时间内再点击无效。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button onclick="testThrottle('arg')">测试节流</button>
<script>
Throttle = function (fn, interval = 1000) {
let timer
return function () {
const context = this, args = arguments
if (!timer) {
fn.call(context, ...args)
timer = setTimeout(() => {
timer = null
}, interval)
}
}
}
testThrottle = Throttle(function (arg) {
console.log(arg)
}, 2000)
</script>
</body>
</html>
重点就是触发clearTimeOut的时机了,防抖中只要触发事件就清掉。而在节流中第一次成功触发才将flag位置为null。用时防抖是将定时器清掉,节流只要保证一段时间内不进入方法。总得来说防抖节流的实现都依赖于闭包和定时器。