闭包
防抖和节流是闭包的一个应用,让我们来先看闭包。
闭包是什么?
函数执行,形成私有的执行上下文,使内部私有变量不受外界干扰,起到保护和保存的作用。
闭包的作用?
保护,避免命名冲突;保存,解决循环绑定引发的索引问题、变量不会销毁、可以使用函数内部的变量、使变量不会被垃圾回收机制回收
闭包的应用?
1、设计模式中的单例模式
2、for循环中保留i的操作
3、防抖和节流
4、函数柯里化
缺点:
会出现内存泄漏的问题
防抖
触发高频函数事件后,n秒内函数只能执行一次,如果在n秒内这个事件再次被触发的话,那么会重新计算时间
<!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>Document</title>
<style>
#debounce {
width: 100px;
height: 100px;
background-color: skyblue;
}
</style>
</head>
<body>
<div>
<button id="debounce">debounce</button>
</div>
</body>
<script>
// 需要防抖的函数
const needed_debounce_function = () => {
console.log('防抖')
}
// 触发高频函数事件后,n秒内函数只能执行一次,如果在n秒内这个事件再次被触发的话,那么会重新计算时间
function debounce(needed_debounce_function, wait_ms) {
console.log(this, arguments) // 为什么这个只执行了一次?是因为debounce()和debounce有区别
// 设置一个计时器
let timer = null
// 关键是它是返回函数的
return function returnFun() {
clearTimeout(timer)
// 过了wait_ms输出的
timer = setTimeout(() => {
needed_debounce_function.apply(this, arguments)
}, wait_ms)
}
}
const button_debounce = document.getElementById('debounce')
button_debounce.addEventListener(
'click',
debounce(needed_debounce_function, 1000)
)
// 区别
// addEventListener('click', debounce())
// addEventListener('click', debounce)
// 也就是说这两个的区别,debounce(): button_debounce绑定的是返回的returnFun函数,debounce: button_debounce绑定的就是debounce函数。
</script>
</html>
节流
高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
<!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>Document</title>
<style>
#throttle {
width: 100px;
height: 100px;
background-color: skyblue;
}
</style>
</head>
<body>
<div>
<button id="throttle">throttle</button>
</div>
</body>
<script>
// 需要节流的函数
const needed_throttle_function = () => {
console.log('节流')
}
// 高频事件触发,但在n秒内只会执行一次,所以节流会 稀释 函数的执行频率
function throttle(needed_throttle_function, wait_ms) {
let canRun = true
return function () {
if (!canRun) return
canRun = false
setTimeout(() => {
needed_throttle_function.apply(this, arguments)
canRun = true //一定时间后才可以运行
}, wait_ms)
}
}
const buttton_throttle = document.getElementById('throttle')
buttton_throttle.addEventListener(
'click',
throttle(needed_throttle_function, 1000)
)
</script>
</html>
应用场景
防抖(debounce)
1、input框用户在不断输入值时,可以用防抖来节约请求资源
2、防止用户无意双击导致重复提交的情况下,可以获取最后一次操作结果并发送给服务器
3、实时保存
节流(throttle)
1、input框用户在不断输入值时,也可以用节流
2、浏览器播放事件,每一秒计算一次进度信息等
3、一般是onresize、onscroll、onmousedown等这些频繁触发的函数,比如你想每隔一秒计算一次位置信息等,然后执行下一步动作(比如防止dom操作让页面卡死)
拓展
1、什么是执行上下文?
2、什么是设计模式中的单例模式?
3、什么是for循环中保留i的操作?
4、什么是函数柯里化?