防抖与节流

汤姆不是猫 ... 2021-11-05 前端
  • JavaScript
  • 性能优化
大约 1 分钟

# 防抖(debounce)

# 🤯 防抖原理:

如果短时间内大量触发同一事件,只会执行一次函数。
在事件被触发n秒后再执行回调,如果在这n秒内又触发,则重新计时。

# 🤔 适用场景:

按钮提交场景:防止多次执行提交,只执行最后一次提交;
服务端验证场景:表单实时验证,只执行连续输入事件的最后一次(类搜索联想词);

# 😃 简化版实现:

const debounce = (fn, delay = 500) => {
    let timeout = null;
    return (...args) => {
        clearTimeout(timeout);
        timeout = setTimeout(() => { 
            fn.apply(this, args);
        }, delay);
    }
}

let sayDebounce = () => {
    console.log('防抖成功')
}

window.addEventListener('scroll', debounce(sayDebounce))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 节流(throttle)

# 🤯 节流原理:

如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。

# 🤔 适用场景:

拖拽场景:固定时间内只允许拖动一次,防止超高频词触发位置变动;
缩放场景:监视浏览器的resize;
动画场景:避免短时间内多次触发动画引起性能问题;

# 😃 简化版实现:

// ①定时器实现
const throttle = (fn, delay = 500) =>{
  let flag = true;
  return (...args) => {
    if(!flag) return;
    flag = false;
    setTimeout(() => {
      fn.apply(this, args);
      flag = true;
    }, delay);
  };
}

// ②时间戳实现
const throttle = (fn, delay = 500) => {
    let preTime = Date.now();
    return (...args) => {
        const nowTime = Date.now();
        if(nowTime - preTime >= delay) {
            preTime = Date.now();
            fn.apply(this, args);
        }
    }
}

let sayThrottle = (e) => {
    console.log(e.target.innerWidth, e.target.innerHeight)
}

window.addEventListener('resize', throttle(sayThrottle))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30