1.防抖:简单来说就是持续触发不执行,不触发了后等一段时间执行
鼠标在一个层中滑动,显示鼠标的坐标
<style>
.box {
500px;
height: 400px;
border-radius: 8px;
border: 1px solid #e6e6e6;
color: #000;
display: flex;
justify-content: center;
align-items: center;
}
</style>
<div class="box" id="box">
function debounce(func,delay){
let timeout;
return function(){
clearTimeout(timeout);
timeout=setTimeout(()=>{
func.apply(this,arguments)
})
}
}
let box=document.getElementById("box");
box.onmousemove=debounce(function(e){
box.innerHTML=`${e.clientX} ${e.clientY}`
},1000)
2.节流:开关打开,持续触发时,持续关闭开关,等到时间到了后打开开关,函数就会执行了
function throttle(func,delay){
let run=true
return function(){
if(!run){
return;
}
run=false
setTimeout(()=>{
func.apply(this,arguments)
run=true
},delay)
}
}
let box=document.getElementById("box");
box.onmousemove=throttle(function(e){
box.innerHTML=`${e.clientX} ${e.clientY}`
},delay)
更新一下:
说明一下节流时,后面操作中应该是因为run=false 所以才直接return,但是不是在return之前let run=ture直接覆盖掉之前的false
这里可以看一下throttle函数内部,和函数调用的时候。首先看函数内部,分解一下结构:
function throttle(func, delay) {
return function () {
// 执行func
}
}
那调用时候呢?也分解一下:
throttle(function () { // 目标函数内容 }, 1000)
这里throttle函数执行的结果是其内部return的function的调用。也就是说鼠标经过的事件监听实际上是这个被return的function,不断持续触发的是它,而throttle函数只是提供了一个作用域,内部用闭包声明了一个run的开关变量,由于闭包的存在,run这个变量会一直存在不被销毁,而let run = true只在这个闭包(可以理解为作用域)内只声明了一次,但它不会被持续执行,所以return的函数内部的判断不会被它覆盖掉。根据打印结果可以看出,事实确实是如此:
